タグアーカイブ Bun

Bun v1.4.1リリース。アイドル時メモリ削減とバンドルサイズ最大85%減の全容

Bun v1.4.1リリース。アイドル時メモリ削減とバンドルサイズ最大85%減の全容

Bun v1.4.1が2026年9月4日にリリースされた。202件の問題を修正し、236件のリアクションに対応したメンテナンスリリースだ。アイドル時のメモリ削減、HTTP/2対応、バンドルサイズの大幅な最適化が含まれている。

特にNext.js SSRのアイドル時RSSは222MBから142MBへ削減された。bun buildではzod 4.5のバンドルサイズが375.3KBから77.3KBへ79%減っている。長期稼働するサーバーや大きなモノレポを扱う開発者にとって、実務に直結する変更だ。

この記事では、実務に影響する主要な変更点をランタイム、bun install、bun build、bun testの順に解説する。

Bun v1.4.1の概要と導入

Bun v1.4.1の概要と導入

BunはNode.js互換のJavaScriptランタイムであり、パッケージマネージャやバンドラー、テストランナーも備える。v1.4.1ではアイドル時のメモリ使用量の削減、Bun.serveのHTTP/2対応、bun buildのバンドル最適化が目玉だ。

インストールとアップグレード

Bunのインストール方法は複数用意されている。macOSやLinuxではcurlコマンド、npmを使う方法、Windowsではpowershellやscoop、macOSではbrew、Dockerイメージも提供される。既存環境のアップグレードは bun upgrade で完了する。

curl -fsSL https://bun.sh/install | bash
npm install -g bun
bun upgrade

このリリースの位置づけ

v1.4.1は202件の問題を修正した。前バージョンv1.4.0で入った回帰の修正も多い。新機能として、ランタイムのメモリ削減、bun installのオフライン対応、bun buildのコード分割改善、bun testの分離実行の修正が盛り込まれた。

ランタイムのメモリ削減と高速化

ランタイムのメモリ削減と高速化

アイドル時のメモリ使用量を大幅削減

BunのJavaScriptエンジンであるJavaScriptCoreが、長時間のアイドル期間後にJIT生成コードを破棄するようになった。これにより、長期稼働するプロセスのメモリ使用量が大きく減る。負荷を60秒かけた後、3分間アイドル状態にしたLinux x64環境のRSSは、Next.js SSRで142MB、vite devで111MB、Expressで53MBだった。前バージョンではそれぞれ222MB、142MB、65MBである。

従来のBun v1.4.0(Before)
Next.js SSR 222 MB
vite dev 142 MB
Express 65 MB
Bun v1.4.1(After)
Next.js SSR 142 MB
vite dev 111 MB
Express 53 MB

上記は60秒の負荷後、3分間アイドル状態にしたときのRSSをLinux x64で比較した結果だ。アイドル時にJITコードを消す仕組みにより、常駐プロセスのメモリコストが抑えられている。

AsyncLocalStorageとBufferの高速化

AsyncLocalStorage.run() が約2倍高速になった。アクティブなストアがあるとき、await.then().finally() のたびに余分なメモリ確保が発生しなくなったためだ。Node.js 26との比較では、als.run() が15.9ns/op、Node.jsの410ns/opに対して大幅に速い。

Bufferの読み書きも高速化された。writeFloatLE() は2.85nsから0.31nsへ9.2倍、writeUInt8() は2.24nsから0.31nsへ7.2倍、readUInt32BE() は0.76nsから0.42nsへ1.8倍速くなった。macOS arm64の計測だ。

モジュール読み込みと表示処理の高速化

組込みNode.jsモジュールの require() が遅延初期化になった。node:assert は6.22msから0.64msへ、node:fs は2.75msから0.87msへ短縮されている。テストやCLIツールの起動時間に効く変更だ。

オブジェクト表示も高速化した。1万6,000個のキーを持つオブジェクトの Bun.inspect() は140msから3.2msへ43倍速くなった。テキストの色付けや console.log()util.inspect() にも同じコードが使われる。

HTTPSの初回接続も最大3倍速くなった。ルート証明書をDER形式で埋め込み、必要になった時だけ解析する方式へ変更したためだ。--use-system-ca を使う場合は46.3msから15.3msへ短縮された。

Bun.serveとWeb APIの強化

Bun.serveとWeb APIの強化

HTTP/2対応とTLS検証の変更

Bun.serve() がHTTP/2を同一ポートでサポートした。TLS接続ではALPNでプロトコルを自動ネゴシエーションし、平文接続ではHTTP/2 prefaceを送ってきたクライアントにHTTP/2で応答する。http1 オプションをfalseにすればHTTP/1.xクライアントを拒否できる。WebSocketとレスポンストレーラーはHTTP/2では未対応だ。

セキュリティ面では、fetch() のTLS検証がURLのホスト名を基準に変更された。従来はカスタム Host ヘッダーをTLSサーバー名として使っていた。プロキシなどでユーザー入力のHostヘッダーを渡す場合があるため、この変更は重要だ。IPアドレスに接続して別名で証明書を検証したい場合は tls.servername を指定する。

WebSocketのpauseとresume

BunのWebSocketクライアントに pause()resume() が追加された。メッセージの処理速度が受信速度に追いつかないとき、TCPソケットからの読み取りを停止できる。停止中はメモリにメッセージが溜まらず、送信側にはTCPバックプレッシャーが伝わる。

const socket = new WebSocket("wss://example.com/feed");

socket.addEventListener("message", (event) => {
  if (!file.write(event.data)) {
    socket.pause();
    file.once("drain", () => socket.resume());
  }
});

これはBun独自の拡張であり、ブラウザでは利用できない。pause中のソケットは socket.isPaused で状態を確認できる。bufferedAmount も送信待ちバイト数を正しく報告するようになった。

Bun.writeのストリーミング書き込み

Bun.write()ResponseReadableStream の本文を、いったんメモリに読み込まずにファイルへストリーミングするようになった。128MiBのダウンロードを書き込むケースでは、ピークRSSの増加が161MBから13MBへ減った。

bun installのオフライン対応とワークスペース改善

bun installのオフライン対応とワークスペース改善

–offlineと–prefer-offline

bun install --offline はネットワーク要求を一切行わない。すべてのパッケージがキャッシュに存在する必要があり、CIでキャッシュを復元するケースやネットワークに接続できないマシン向けだ。キャッシュに無いパッケージがあると、その名前を明示したエラーになる。

bun install --prefer-offline はキャッシュを優先する。期限切れでもキャッシュのコピーを使い、キャッシュに無いパッケージだけダウンロードする。どちらも bunfig.toml に設定すればデフォルトにできる。

通常の bun install
キャッシュの有効期限が切れると、新しいバージョンを確認するためメタデータを再取得する
bun install –prefer-offline
期限切れでもキャッシュを優先する。キャッシュにないパッケージだけダウンロードする
bun install –offline
ネットワーク要求を一切行わない。キャッシュに無いパッケージがあればエラーになる

self-contained node_modules

ワークスペースのpackage.jsonに "selfContained" を指定すると、そのパッケージ専用の node_modules が作られる。Electronのように特定の node_modules レイアウトを期待するツール向けだ。Yarnの hoistingLimits 設定も利用できる。

bun buildのバンドル最適化とコンパイル改善

bun buildのバンドル最適化とコンパイル改善

export * asによるバンドルサイズ削減

zodやEffectのように export * as でエクスポートをまとめるライブラリで、未使用エクスポートのツリーシェイクが効くようになった。v1.4.0では z.object() を呼んだ場合でもグループの全エクスポートを保持していた。v1.4.1では直接参照にコンパイルされ、不要なエクスポートが削除される。

Bun v1.4.0(Before)
zod 4.5 375.3 KB
fp-ts 2.16 21.8 KB
effect 3.22 369.1 KB
Bun v1.4.1(After)
zod 4.5 77.3 KB (79%削減)
fp-ts 2.16 3.2 KB (85%削減)
effect 3.22 163.6 KB (56%削減)

各ライブラリから2〜3個の関数だけを呼ぶ小規模なプログラムを、bun build --minify でビルドした結果だ。zodでは252個のエントリを持つ名前空間オブジェクトが生成されていたが、v1.4.1ではすべて削除された。

動的importのtree-shakingとコード分割

import() で読み込むモジュールでも、未使用のエクスポートが削除されるようになった。const { z } = await import("zod") は静的な import { z } from "zod" と同じコードにバンドルされる。zod 4.5では377.9KBから78.2KBへ縮む。

--splitting も改善された。40個の遅延ルートを持つテストアプリでは、出力ファイルが219個から151個に、出力サイズが124KBから75KBに減った。さらに --min-chunk-size オプションで小さなチャンクを統合できる。ブラウザ向けビルドでは link rel="modulepreload" が自動追加され、チャンクのフェッチが並列化される。

–compileの起動高速化とバイトコード削減

コンパイル済み実行ファイルの起動も速くなった。BunでコンパイルされたClaude Codeでは、入力ボックスが表示されるまでの時間が397msから318msへ20%短縮された。バイトコードのサイズも最適化され、これまで元ソースの約9倍だったものが約3倍になった。Claude Codeのインストールサイズは376MBから207MBへ45%減っている。

--bytecode-depth で事前コンパイルする関数のネスト深度を制限できる。--bytecode を付けたクロスコンパイルもmacOSやLinuxからWindows x64へ対応した。テキストインポートは1回だけ埋め込まれ、実行時の解析とコピーが不要になった。

この記事のポイント

  • Bun v1.4.1は202件の問題を修正し、アイドル時のメモリ使用量を大幅に削減した
  • Bun.serveがHTTP/2に対応し、WebSocketにpauseとresumeが追加された
  • bun installにオフラインモードが加わり、CIやネットワーク遮断環境で使いやすくなった
  • bun buildはzodやEffectのバンドルサイズを最大85%削減し、コード分割も改善した
  • bun build –compileは起動時間とバイトコードサイズを最適化した