Bun で実行可能バイナリをクロスコンパイルできるようになりました

| 4 min read
Author: masahiro-kondo masahiro-kondoの画像

はじめに

#

去年の9月 Bun が 1.0 に到達したとき、開発環境に導入してみた記事を書きました。

開発環境の Node.js を Bun に置き換えてみる

その後 Bun 1.1 で Windows 対応が行われ、真のクロスプラットフォームが実現されました。

Bun 1.1 | Bun Blog

実行可能バイナリを生成する機能は提供されていましたが、1.1.5 でクロスコンパイルの機能が実装されました。

Bun v1.1.5 | Bun Blog

宣伝 - Software Design 2024年6月号の Bun 特集に寄稿しました

冒頭で紹介した記事がきっかけで、Software Design 2024年6月号第2特集の Bun に寄稿する機会を得ました。以下のように Bun の概要から利用方法、Node.js とのパフォーマンス比較を網羅する特集です。

  • 第1章: Bun の全体像をつかむ
  • 第2章: Bun を使ってみよう
  • 第3章: Bun と Node.js の徹底比較

筆者は2章の執筆を担当させていただきました。Bun のインストールから各機能の紹介と利用方法、デバッグ方法などについて書きました。執筆時点では Bun 1.1 のリリース直後で、クロスコンパイルについては触れられませんでした。実行可能バイナリの作成については紹介しています。
第3章は Node.js と Bun のコードを AWS Lambda にデプロイして速度比較するなど、興味深い内容となっています。

SD202406

Software Design 2024年6月号

シングルバイナリおよびクロスコンパイルの利点

#

シングルバイナリ化することのメリットは、ユーザーに対する配布の利便性はもちろんのこと、以下のような利点もあります。

  • 実行時に import 解決、トランスパイル、コード生成の処理が不要になるため時間とメモリが節約できる
  • バイナリのコピーだけでコンテナ化が可能でランタイム不要なので軽量コンテナにできる
  • バイナリを CI で利用する場合、ダウンロードしてパスを通すだけで実行できるのでパイプラインがシンプルになり、実行時間の節約になる

さらにクロスコンパイルができると以下のような利点があります。

  • 対象の環境ごとにビルド環境を用意する必要がない
  • 1つの CI パイプラインで全ターゲットの実行可能バイナリをビルドできる

このため、もともとオールインワンを売りとする Bun にクロスコンパイルの機能が実装されたことで、開発からクロスプラットフォームへの実行可能バイナリ配布まで bun CLI 一つで賄えることになり、開発体験はかなり向上したと言えるでしょう。

Bun のクロスコンパイルを試す

#

では、Bun の実行可能バイナリの生成とクロスコンパイルを試してみましょう。筆者は macOS Sonoma / Bun 1.1.8 の環境で実施しています。

Bun のプロジェクトを作成します。

mkdir simple-server && cd simple-server
bun init -y

ポート3000番で待ち受けてメッセージを返すだけの簡単な HTTP サーバーを書きました。

index.ts
Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response('Hello, Bun!')
  }
});

このコードは次のコマンドで実行可能です。

bun index.ts

実行可能バイナリを作成してみます。

$ bun build --compile ./index.ts --outfile simpleServer
   [2ms]  bundle  1 modules
 [104ms] compile  simpleServer

約0.1秒でビルドが完了し、macOS のマシンをターゲットとする51MBの実行可能バイナリが生成されました。

$ ls -lh simpleServer
-rwxrwxrwx  1 kondoh  staff    51M  5 20 14:50 simpleServer

以下のように bun CLI なしで実行できます。

./simpleServer

上記の例では、ターゲットを指定しませんでしたが --target オプションでプラットフォームを指定できます。Windows 用のバイナリを生成してみましょう。

$ bun build --compile ./index.ts --target=bun-windows-x64 --outfile simpleServer.exe
   [3ms]  bundle  1 modules
[4.302s] compile  simpleServer.exe bun-windows-x64-v1.1.8

必要なライブラリのダウンロードを含めて4.3秒ほどでビルドが完了しました。ファイルサイズは100MBぐらいです。

$ ls -lh simpleServer.exe
-rwxrwxrwx  1 kondoh  staff   105M  5 20 14:55 simpleServer.exe

--target の指定は以下のようになっています。

プラットフォーム --target の値
Linux x64 bun-linux-x64
Linux ARM bun-linux-arm64
Windows x64 bun-windows-x64
macOS x64 bun-darwin-x64
macOS Apple Silicon bun-darwin-arm64

プロダクションへのデプロイ時には、--minify--sourcemap の指定も推奨されています。

bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp

--minify オプションを指定することでトランスパイルされたコードのサイズを小さくできます。--sourcemap オプションを指定することでオリジナルのソースコードの位置でエラー情報を出力させることが可能です。

その他、アセットの埋め込みや SQLite データベースの埋め込みもサポートされています。詳細はドキュメントを参照してください。

Single-file executable – Runtime | Bun Docs

主要ランタイムでの実装状況

#

実行可能バイナリの生成については、Node.js と Deno でも実装されており、クロスコンパイルについては Deno にも既に実装されています。

Deno Bun Node.js
実行可能バイナリの生成 ⚪︎ ⚪︎ ⚪︎ (Active development)
クロスコンパイル ⚪︎ ⚪︎ -

Node.js の Single Executable Applications に関しては、stability: 1.1 - Active development のステータスであり、現時点では安定版とは言えません。後発のランタイム Deno と Bun が肩を並べたという状況です。

Information

昨年の記事ですが、本サイトでは Node.js の Single Executable Applications について以下の記事で取り上げています。

Node.js v19.7で実験的に導入された Single Executable Applications で単独実行可能ファイルを作成する

さいごに

#

以上、Bun で実装された実行可能バイナリのクロスコンパイルを試してみました。
実行可能バイナリによってデプロイ環境でのフットプリントを小さく起動を速くできることは大きなメリットです。
最終的には、CI でエンドツーエンドのテストをターゲットプラットフォームごとに実施する必要はありますが、クロスコンパイル機能により開発環境は1プラットフォーム分だけあればよいのは嬉しいところです。

豆蔵では共に高め合う仲間を募集しています!

recruit

具体的な採用情報はこちらからご覧いただけます。