RustはフロントエンドおよびJavaScriptにおけるツールで欠かせない存在となりました。
JavaScriptランタイムDenoや、高速なフォーマッター・リンターBiome、トランスパイラーSWCなどです。
我々は npm install
などで知らず知らずのうちにRustで作られたソフトウェアをインストールし、利用しています。
これに気づかないのは、我々はRust環境(rustupやcargo)をセットアップせずとも利用できるからです。
さて、どのようにしてRustコードは我々のコンピュータで動いているのでしょうか。
1. WebAssembly
1つ目はWebAssembly、通称WASM(ワズム)です。Rustおよびその周辺ツールチェーンではRustをWASMに変換するソリューションが提供されています。
rustc(Rustコンパイラ)はwasm出力に対応し、wasm-bindgenやwasm-packを用いることでRust用のインターフェースやJavaScriptのグルーコードが提供されます。
wasm-bindgenやwasm-packを利用して出力したWASMも当然Node.jsから利用できます。
ブラウザとNode.js、その他JavaScriptランタイムで同一のRustコードを動かす場合、これが第一の選択肢になるでしょう。
また、WebAssembly System Interface、通称WASI(ワズィ)というものもあります。
WASIはWASMのスーパーセットであり、ブラウザ以外での利用が主になります。Node.jsでもWASIのためのAPIがExperimentalで用意されており(2024/12/04現在)、利用することができます。
WASMはポータビリティに優れ、OS間の差異がないため今後さらなる流行が期待できます。しかしながらWASIによって改善しつつあるものの、ファイルシステムやネットワーク通信を扱うようなケースではエコシステムが未成熟と言わざるを得ません。
これら技術を用いたソフトウェアとして以下のようなものがあります:
-
amaro (Node.jsでTypeScriptを動かすためのtransformer)
- amaroはwasm-packを用いてWASMが生成されています
-
Rolldown
- 一部WASIが利用されています
2. Node-API (N-API)
Node-APIは、ネイティブ技術をNode.jsから利用するためのAPIです。ネイティブのバイナリを用いるのでNode.jsのJavaScriptやWASMよりも高速に動作します。
Rustでは、NAPI-RSを筆頭にNode-APIをサポートしたツールチェインが存在しており、これを利用することでRustコードをネイティブの速度でNode.jsから利用することができます。
Node-APIはネイティブの速度を手に入れつつ、Node.jsとの通信も確立されている技術です。ネイティブで制約がない故に、セキュリティ面の懸念があるほか、OS別にバイナリを配布する必要があるなどいい面ばかりではありません。
この技術を用いたソフトウェアとしては以下のようなものがあります:
-
Rolldown
- NAPI-RSでRustコードがバイナリに変換され主に利用されます
-
Rollup
- 以前はJavaScriptで書かれていましたが、現在はパース処理がRust(SWC)製のものになっています
3. child_process
Node.jsにはchild_processというモジュールがあり、実行可能形式のファイルを実行することができます。
Rustを実行可能形式のバイナリとして出力して、child_processモジュールのexec関数などを利用することでRustコードを実行できます。
child_process、というか実行可能形式では、ネイティブの速度を手に入れつつ、Node.js以外のDenoやその他言語からもその気になれば利用できます。Node-APIと同様セキュリティやOS別バイナリなどのデメリットに加え、Node.jsと直接通信ができないという問題もあります。
この技術を用いたソフトウェアとしては以下のようなものがあります:
-
Biome
- Biomeは実行可能形式のファイルを配布し、execすることで実現されています
まとめ
ポータビリティ | Node.jsとの通信 | セキュリティ | 速度 | ツールチェイン | |
---|---|---|---|---|---|
1a. WASM | ◎(ブラウザでもOK) | ○ | ◎ | ○ | ○ |
1b. WASI | ◎ | ○ | ○ | ○ | △ |
2. Node-API | ×(Node.js限定,OS別バイナリ) | ○ | △ | ◎ | ○ |
3. child_process | △(OS別バイナリ) | △ | △ | ◎ | ◎ |