初心者向け WebAssembly のパート 4 では、WebAssembly と JavaScript の関係を詳しく見ていきます。
ここでは、JavaScript で WebAssembly を使用する方法を学びます。さらに、WebAssembly JavaScript API についても説明します。
WebAssembly は、開発者がブラウザ上でネイティブ パフォーマンスでアプリを実行できるようにするバイナリ形式のオープン スタンダードです。まだ読んでいない場合は、ガイドの前の部分を確認することをお勧めします。
- 初心者のための WebAssmebly パート 1: WASM の概要
- 初心者のための WebAssembly パート 2: 目標、重要な概念、使用例
- 初心者のための WebAssembly パート 3: WASM の移植性とセキュリティの仕組み
始めましょう。

JavaScript での WebAssembly の使用
WebAssembly パート 1 チュートリアルでは、WASM がどのように機能するかについて説明しました。 Web アプリ用に高パフォーマンスのコードを作成するには、JavaScript 内で WASM API と関数を使用する必要があります。また、JavaScript フレームワークが WASM を使用して高パフォーマンスのアプリを作成する方法についても説明しました。
ただし、現在、<script type=” module”> を使用して ES6 モジュールなどの WASM モジュールをロードすることはできません。そこで JavaScript が登場します。JavaScript は、ブラウザ上での WASM のロードとコンパイルに役立ちます。そのための正確な手順は次のとおりです。
- .wasm バイトを ArrayBuffer または型付き配列にロードします。
- WebAssembly.Module を使用してバイトをコンパイルします。
- 次に、インポートを使用して WebAssembly.Module をインスタンス化し、呼び出し可能なエクスポートを取得します。
したがって、事前にコンパイルされた WASM モジュールを使用して開始する必要があります。ここでは、たくさんの選択肢があります。 Rust、C/C++、AssemblyScript、さらには TinyGo(Go) を使用してコードを作成し、後でそれを .wasm モジュールに変換できます。
技術的には、WebAssembly は言語のコンパイル ターゲットです。つまり、選択した言語でコードを記述し、生成されたバイナリ コードをアプリケーション (Web または非 Web) 内で使用する必要があります。さらに、サーバー上で使用する場合は、システムとのインターフェースに WASI を使用する必要があります。
WebAssembly は拡張可能な配列を介して線形メモリを使用するため、JavaScript と WASM の両方が同期的にアクセスできるため、機能が豊富で高速なアプリを作成できます。

WebAssembly と JavaScript の例
例を使用して、JavaScript で WASM を使用する方法を学びましょう。
上で述べたように、事前にコンパイルされた WASM モジュールが必要です。この例では、Emscripten (C/C++) を使用します。 WASM は高性能のバイナリ形式を提供するため、生成されたコードを JavaScript や他の言語と並行して実行できます。
ツールのセットアップ
Emscripten を使用しているため、 emsdk ツールを入手する必要があります。これにより、C/C++ コードを .wasm コードにコンパイルできるようになります。
ターミナルで次のコマンドを実行するだけです。 GIT がインストールされていない場合は、「オープンソース 101: バージョン管理システムと Git ガイド」に従ってインストールしてください。
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
#Output
nitt@nitt-laptop:~/Projects/WASM2$ git clone https://github.com/emscripten-core/emsdk.git
Cloning into 'emsdk'...
remote: Enumerating objects: 3566, done.
remote: Counting objects: 100% (62/62), done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 3566 (delta 31), reused 38 (delta 13), pack-reused 3504
Receiving objects: 100% (3566/3566), 2.09 MiB | 2.24 MiB/s, done.
Resolving deltas: 100% (2334/2334), done.
nitt@nitt-laptop:~/Projects/WASM2$ cd emsdk
nitt@nitt-laptop:~/Projects/WASM2/emsdk$
emdsk フォルダーで、別のコマンドを呼び出して、すぐに使用できる最新の Emscripten ビルドを取得します。
これを行うには、次のコマンドを実行する必要があります。
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
#Output
nitt@nitt-laptop:~/Projects/WASM2/emsdk$ ./emsdk install latest
Resolving SDK alias 'latest' to '3.1.31'
Resolving SDK version '3.1.31' to 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'
Installing SDK 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'..
Installing tool 'node-14.18.2-64bit'..
Downloading: /home/nitt/Projects/WASM2/emsdk/zips/node-v14.18.2-linux-x64.tar.xz from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz, 21848416 Bytes
Unpacking '/home/nitt/Projects/WASM2/emsdk/zips/node-v14.18.2-linux-x64.tar.xz' to '/home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit'
Done installing tool 'node-14.18.2-64bit'.
Installing tool 'releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'..
Downloading: /home/nitt/Projects/WASM2/emsdk/zips/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-wasm-binaries.tbz2 from https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a/wasm-binaries.tbz2, 349224945 Bytes
Unpacking '/home/nitt/Projects/WASM2/emsdk/zips/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-wasm-binaries.tbz2' to '/home/nitt/Projects/WASM2/emsdk/upstream'
Done installing tool 'releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'.
Done installing SDK 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'.
nitt@nitt-laptop:~/Projects/WASM2/emsdk$ ./emsdk activate latest
Resolving SDK alias 'latest' to '3.1.31'
Resolving SDK version '3.1.31' to 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'
Setting the following tools as active:
node-14.18.2-64bit
releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit
Next steps:
- To conveniently access emsdk tools from the command line,
consider adding the following directories to your PATH:
/home/nitt/Projects/WASM2/emsdk
/home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin
/home/nitt/Projects/WASM2/emsdk/upstream/emscripten
- This can be done for the current shell by running:
source "/home/nitt/Projects/WASM2/emsdk/emsdk_env.sh"
- Configure emsdk in your shell startup scripts by running:
echo 'source "/home/nitt/Projects/WASM2/emsdk/emsdk_env.sh"' >> $HOME/.bash_profile
最後のコマンドは「source ./emsdk_env.sh」です。これにより、emcc Emscripten コンパイラ ツールのパスが確実に設定され、それを使用してコードをコンパイルできるようになります。
#Output
nitt@nitt-laptop:~/Projects/WASM2/emsdk$ source ./emsdk_env.sh
Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)
Adding directories to PATH:
PATH += /home/nitt/Projects/WASM2/emsdk
PATH += /home/nitt/Projects/WASM2/emsdk/upstream/emscripten
PATH += /home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin
Setting environment variables:
PATH = /home/nitt/Projects/WASM2/emsdk:/home/nitt/Projects/WASM2/emsdk/upstream/emscripten:/home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
EMSDK = /home/nitt/Projects/WASM2/emsdk
EMSDK_NODE = /home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin/node
nitt@nitt-laptop:~/Projects/WASM2/emsdk$
ここで、次のコマンドを実行して wasm コードを生成する必要があります。
emcc hello-.c -o hello-.js
#Output
nitt@nitt-laptop:~/Projects/WASM2$ emcc hello-.c -o hello-.js
shared:INFO: (Emscripten: Running sanity checks)
cache:INFO: generating system asset: symbol_lists/1c683af19e290d0b5ca7a8747d74a76f63dcb362.txt... (this will be cached in "/home/nitt/Projects/WASM2/emsdk/upstream/emscripten/cache/symbol_lists/1c683af19e290d0b5ca7a8747d74a76f63dcb362.txt" for subsequent builds)
cache:INFO: - ok
nitt@nitt-laptop:~/Projects/WASM2$ dir
emsdk hello-.c hello-.js hello-.wasm
nitt@nitt-laptop:~/Projects/WASM2$
ご覧のとおり、「hello-.js」と hello-.wasm の出力が得られます。プロジェクト ディレクトリで dir を実行すると、ファイルを確認できます。
これらのファイルは両方とも必須です。 hello-geefklare.wasm にはコンパイルされたコードが含まれています。一方、 hell-geefklare.js ファイルには、実行に必要な JavaScript が含まれています。 Emscripten は Web および Node.js の実行をサポートしているため、Node.js を使用してテストできます。
node hello-.js
#Output
nitt@nitt-laptop:~/Projects/WASM2$ node hello-.js
Hello, GeekFlare!
nitt@nitt-laptop:~/Projects/WASM2$
Web 上で実行されるのを確認したい場合は、Emscripten を使用して HTML ファイルを生成できます。これを行うには、次のコマンドを実行します。
emcc hello-.c -o hello-.html
#Output
nitt@nitt-laptop:~/Projects/WASM2$ emcc hello-.c -o hello-.html
nitt@nitt-laptop:~/Projects/WASM2$
HTML ファイルを実行するには、次のコマンドを実行して Python 3 HTTPServer を使用できます。
python3 -m HTTP.server 8000
次に、 http://localhost:8000/hello-.html に移動して出力を確認します。
注: ほとんどのシステムには Python がプリインストールされています。そうでない場合は、Python3 サーバーを実行する前に簡単にインストールできます。

JavaScript API を使用した WASM の操作
このセクションでは、JavaScript WASM API について詳しく説明します。これを使用して、WASM コードをロードして実行する方法を学びます。まずは、以下のコードを見てみましょう。
fetch('hello-.wasm').then( response =>
response.arrayBuffer())
.then (bytes =>
WebAssembly.instantiate(bytes))
.then(result=>
alert(result.instance.exports.answer()))
上記のコードでは、次の JavaScript API を使用します。
- fetch() ブラウザ API
- WebAssembly.instantiate
これら以外にも、注目に値する API があります。これらには次のものが含まれます。
- WebAssembly.compile
- WebAssembly.instance
- WebAssembly.instantiate
- WebAssembly.instantiateStreaming
fetch() ブラウザ API
fetch() API は .wasm ネットワーク リソースをロードします。ローカルでロードしようとしている場合は、クロスオリジン リソース共有を無効にして、ネットワーク リソースをロードする必要があります。それ以外の場合は、ノード サーバーを使用してそれを行うことができます。ノード サーバーをインストールして実行するには、次のコマンドを実行します。
sudo apt install npm
次に、次のコマンドを実行してサーバーを実行します。
npx http-server -o
#Output
http-server version: 14.1.1
http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none
Available on:
http://127.0.0.1:8080
http://192.168.0.107:8080
Hit CTRL-C to stop the server
Open: http://127.0.0.1:8080
[2023-01-28T19:22:21.137Z] "GET /" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70"
(node:37919) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
(Use `node --trace-deprecation ...` to show where the warning was created)
[2023-01-28T19:22:21.369Z] "GET /favicon.ico" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70"
[2023-01-28T19:22:21.369Z] "GET /favicon.ico" Error (404): "Not found"
Web ブラウザが開き、すべてのプロジェクト ファイルが表示されます。
次に、hello-geefklare.html を開いて、Web 開発者ツールを実行します。そこでコンソールを開き、次のように入力します。
fetch(“hello-.wasm”);
次の Promise を返します。
#Output
Promise {<pending>}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Response
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://127.0.0.1:8080/hello-.wasm"
[[Prototype]]: Response
次のスクリプトを作成し、HTML 経由で実行することもできます。
wasm モジュールをサーバー上で実行するには、Node.js で次のコードを使用する必要があります。
const fs = require('fs');
const run = async() => {
const buffer = fs.readFileSync("./hello-.wasm");
const result = await WebAssembly.instantiate(buffer);
console.log(result.instance.exports.answer());
};
run();
詳細については、 WebAssembly JavaScript API ドキュメントを読むことをお勧めします。

JavaScript とWASM
WASM と JavaScript の関係を理解するには、それらを比較する必要もあります。本質的には、WASM の方が高速で、ターゲットのコンパイルにバイナリ形式を使用しますが、JavaScript は高級言語です。 WASM のバイナリ コードは学習を困難にしますが、WASM を効率的に操作する方法はあります。
WASM と JavaScript の主な違いは次のとおりです。
- WASM はコンパイル言語ですが、JS はインタプリタ言語です。ブラウザは実行時に JavaScript をダウンロードして解析する必要がありますが、WASM コードは事前にコンパイルされたコードですぐに実行できます。
- WebAssembly は低レベル言語です。対照的に、JavaScript は高級言語です。 JS は高レベルなので扱いやすいです。ただし、WASM は低レベルなので、JavaScript よりもはるかに高速に実行できます。
- 最後に、JavaScript は大規模なコミュニティの恩恵を受けています。したがって、より優れた開発エクスペリエンスを探している場合は、JS を選択するのが明らかです。一方、WebAssembly は比較的新しいため、リソースが不足しています。
開発者は、どれを選択するかについて心配する必要はありません。これは、JS と WASM の両方が相互に対立するのではなく、連携して動作するためです。
したがって、高パフォーマンスのアプリを作成している場合は、WebAssembly を使用してパフォーマンスが必要な部分のみをコーディングするとよいでしょう。 JavaScript API は、WASM モジュールを JavaScript コードに直接取得して使用するのに役立ちます。
最終的な考え
結局のところ、WebAssembly は JavaScript の優れたパートナーです。開発者は、Web および非 Web 上で高性能のアプリケーションを作成できます。さらに、JavaScript を置き換えることなくそれを実行します。
しかし、WASM は完全なパッケージに進化し、JavaScript を置き換えるのでしょうか? WebAssembly の目標を考慮すると、それはおそらく不可能ですが、不可能です。ただし、WebAssembly が将来 JavaScript に置き換わるという考えは完全に反駁できるわけではありません。
次に、最新のアプリケーションを構築するための最適な JavaScript (JS) UI ライブラリを確認してください。
