NodeなしでNodeを実行してみた
TL;DR
Nodeの実行環境を含めたバイナリファイルを出力できる新機能が追加された。
これを使うとNodeなしにNodeのプログラムが実行できるようになる。
新機能「Single executable applications」
NodeJSのv20.0.0から新機能「Single executable applications」が追加されました。
CommonJSのコードをバイナリとして出力し、NodeJSが存在しない環境でも実行できるようにしてくれます。この機能は「experimental」で本実装されているわけではないのですが、面白そうなので遊んでみました。
コンパイル
実行はdocker上で行います。imageはbullseye(debian11)を使用しました。
$docker run -it node:20-bullseye-slim bash
公式のドキュメントに従い、以下を実行していきます。
hello.jsを作成
$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
コンパイルの設定ファイルを作成
$ echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
中間ファイルを作成
$ node --experimental-sea-config sea-config.json
nodeをコピー
$ cp $(command -v node) hello
バイナリファイルの結合
$ npx postject hello NODE_SEA_BLOB sea-prep.blob \
--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
これで、「hello」ファイルが作成されました。
実行
$ ./hello world
hello world
バイナリを実行できた!!!!
感想
本質的には、Node.jsの実行スクリプトと作成したファイルを一緒にして、単一のバイナリファイルを作成しているような内容になっています。このため、出力されたバイナリファイルをそのまま本番環境に簡単にデプロイできるのが利点です。
例えば、あるバージョンのNode.jsが稼働しているサーバーに、別バージョンのNode.jsのアプリケーションをデプロイする際に利用できます。実行環境に触れずにアプリケーションを実行できるのは大きな利点になることがあると思われます。オンプレミス環境では、このようなケースがまだ存在する可能性があると考えられます。
注意点
自分のローカル環境ではこのコマンドは正常に動作せず、dockerでの動作を確認しています。nodenvでnodeをインストールしている影響かと思われます。
以下のコード実行時に吐かれるhello
ファイルがnodeのバイナリファイルではなく、nodenvのシェルスクリプトになっていたのが直接の原因に思われます。
$ cp $(command -v node) hello
Dockerであれば生のNode.jsを利用できるため、本記事ではDockerの上でコマンドを実行しています。
Discussion