esbuildとは?Go製の高速バンドラの使い方と採用判断を実装目線で解説
esbuildは、JavaScriptとCSSをまとめて出力するGo製のバンドラ兼圧縮ツールです。npm registryで2026年8月1日に確認したlatestは0.28.1で、公式は自らを「極めて高速なJavaScriptおよびCSSのバンドラかつミニファイア」と説明しています。速さの一点に振り切った設計のため、できることとできないことの線がはっきりしているのが特徴。この記事では、速度を生む4つの設計、npm導入からCLIとJavaScript APIの使い方、TypeScriptとCSSの扱い、ViteやwebpackやSWCとの違い、そして受託開発で採用してよい条件までを実装目線で扱います。
まとめ:esbuildを採用してよい条件と別ツールに任せる線引き
結論から示します。ビルドの速さが効く場面、具体的には社内ツール、CLI、ライブラリのビルド、テストの前処理、Lambdaなどの関数バンドルであれば、esbuild単体で十分に成立します。設定ファイルの規約を持たず、CLIの1行かJavaScript APIの十数行で完結する構成の軽さが効いてくる領域。TypeScriptもJSXもCSSも追加のプラグインなしで通ります。
一方で、esbuild単体を見送る判断が要るのは3つの場合です。第一に型検査やデコレータのメタデータ出力に依存する構成。esbuildは型情報を持たないため、tscを別プロセスで走らせる前提になります。第二にVueやSvelteのような専用の構文を持つフレームワーク。第三にコード分割の細かい制御や成熟したプラグイン生態系を必要とする大規模SPAです。この3つに当たるなら、ViteやRollupやwebpackを土台に据え、esbuildは内部の部品として間接的に使う形へ寄せてください。
esbuildの定義|Go製バンドラが10倍以上速い4つの理由
まず、esbuildが何をするものなのかを設計の狙いから押さえます。ここを飛ばすと、後段のオプションや制約が単なる暗記事項になってしまいます。
Goネイティブコード化と並列処理と3パス設計が生む速度差の理屈
公式FAQは、速さの理由として4点を挙げています。1つ目がGoで書いてネイティブコードへコンパイルしている点。多くのバンドラはJavaScript製で、Node.jsがバンドラ自身のコードを解析し終える頃にはesbuildが処理を終えている、という書き方で差を説明しています。2つ目が並列処理で、Goの共有メモリ型の並行モデルを使い、解析からコード生成までを複数コアへ広げます。
3つ目が実装をすべて自前で書いている点です。サードパーティのライブラリに寄りかからないため、データ構造を統一でき、設計の自由度が残ります。4つ目がメモリの使い方で、JavaScriptのASTに対する走査を3回に抑え、CPUキャッシュの再利用を効かせる設計。バンドラー一般の仕組みから整理したい場合は、Rollupで学ぶJavaScriptバンドラーの基礎が土台になります。
バンドラとトランスパイラを兼ねる守備範囲と実装されない機能群
esbuildは、依存を辿ってひとつにまとめるバンドラと、新しい構文を古い構文へ落とすトランスパイラの両方を兼ねます。加えて出力の圧縮も自前で持つため、この3つを別々のツールで組む必要がありません。公式は自らの立ち位置を「Web向けのリンカ」と表現しており、何でも入りの統合ツールを目指していない点を明言しています。
裏返すと、実装しないと明言している領域があります。型検査、.d.tsの生成、Vue・Svelte・Angularといった独自構文への対応、AST操作の公開API、ホットモジュールリプレースメントの5つ。コード分割については実装済みながら公式が「まだかなり原始的」と書いており、成熟度は一段落ちる扱いです。これらが要る構成では、esbuildを土台にせず部品として組み込む設計へ寄せる判断になります。
| 領域 | esbuildの扱い |
|---|---|
| 型検査 | 非対応・tscを併用 |
| .d.ts生成 | 非対応 |
| Vue・Svelte | 非対応・プラグイン頼み |
| AST操作API | 公開予定なし |
| HMR | 非対応・再読み込みのみ |
| コード分割 | 実装済みだが発展途上 |
0.28系という版番号とマイナー版で入る破壊的変更への備え方
成熟度の話で外せないのが版番号です。npm registryで2026年8月1日に確認したlatestは0.28.1で、1.0には到達していません。公式は現状を「後期ベータ」と位置づけたうえで、ViteやAmazon CDKといった規模の大きいプロジェクトで広く使われてきた実績も併記しています。開発の中心が実質1名という体制も、採用判断では前提として置いてください。
0.x系のため、破壊的変更はパッチ版ではなくマイナー版の更新で入ります。公式の導入手順がnpm install --save-exact --save-dev esbuildとバージョン固定を指定しているのはこのため。キャレット付きで入れると、依存の更新だけでビルド結果が変わる事故につながります。CIでは版を固定し、更新は変更履歴を読んでから手動で上げる運用が安全側です。
esbuildの導入方法とCLI・JavaScript APIの基本的な使い方
次に、実際に動かす手順を確認します。設定ファイルの規約が存在しないため、覚えることはコマンドかAPIの引数だけです。
npmでの導入とバンドル1行を走らせる最短のCLIコマンド手順
導入はnpmが基本で、環境に合うネイティブバイナリが自動で降りてきます。プラットフォームが対応外ならesbuild-wasmという逃げ道もあるものの、速度は大きく落ちる点に注意。ほかにDeno向けの配布やGoからのソースビルドも用意されています。
npm install --save-exact --save-dev esbuild
./node_modules/.bin/esbuild app.jsx --bundle --outfile=out.js
この2行で、JSXを含むReactアプリが1ファイルへまとまります。拡張子が.jsxならJSX構文は自動で判定されるため、追加の指定は不要。package.jsonのscriptsへ同じコマンドを置けば、npm run buildで呼び出せます。設定ファイルを別途置く必要がない点が、導入の速さに直結しています。
build APIとtransform APIの使い分けとcontextの役割
JavaScript APIは大きく2つに分かれます。build APIはファイルシステム上のファイルを入口にバンドルまで行い、プラグインも使えます。transform APIはメモリ上の文字列だけを対象とし、TypeScriptからJavaScriptへの変換や圧縮に向く一方、バンドルとプラグインは使えません。ビルドツールの内部から呼ぶ場合はtransform、アプリのビルド本体を任せる場合はbuildという切り分けになります。
import * as esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['app.jsx'],
bundle: true,
minify: true,
sourcemap: true,
target: ['chrome58', 'firefox57', 'safari11'],
outfile: 'out.js',
})
増分ビルドが要るならcontextを使います。esbuild.context()で作った文脈オブジェクトは、ファイルのキャッシュとASTを再利用しながら、watchモード、ローカル開発サーバーを立てるserveモード、任意のタイミングで呼ぶrebuildの3つを提供。使い終えたらdispose()を呼んでプロセスを終了させます。呼び忘れるとwatchやserveが残り続けるため、スクリプトの後始末に必ず入れてください。
バンドル時に効く主要オプションと本番ビルド向けの指定の組み方
オプションは数が多いものの、実務で触るのは限られます。出力形式を決めるformatはiife、cjs、esmの3種。実行環境を決めるplatformはbrowser、node、neutralの3種で、nodeを選ぶと組み込みモジュールが自動で外部扱いになります。ブラウザ向けならtargetで対応ブラウザを並べ、古い構文へ落とす範囲を決めてください。
| オプション | 役割 |
|---|---|
| bundle | 依存を辿って1本化 |
| minify | 出力を圧縮して縮める |
| splitting | 共通コードを分割 |
| external | 特定パッケージを除外 |
| packages | externalで依存を全除外 |
| sourcemap | ソースマップを出力 |
| loader | 拡張子ごとの解釈を指定 |
本番向けは--minifyと--targetを、開発向けは--sourcemapを足すのが基本形です。Node.js向けにサーバーコードを束ねるなら--platform=nodeに加えて--packages=externalを指定し、node_modulesを実行時に解決させる構成が扱いやすい形。逆にLambdaのように配布物を単体で完結させたい場合は、依存を含めて1本にまとめる指定へ振ります。
TypeScriptとCSSの扱い|型検査を持たない設計の実務対応
ここからはTypeScriptとCSSという、実務で必ず当たる2つの入力を見ます。どちらも標準で通る一方、前提条件が付きます。
型検査を行わない前提でtscを別プロセスに分ける運用の設計手順
esbuildはTypeScriptの型をコメントと同じように読み飛ばします。型情報を持たないので、型エラーはビルドを止めません。この設計はビルドを速くする代わりに、型検査の責任を外へ出します。手元ではtsc --watch --noEmitを別プロセスで走らせ、CIでは型チェックのステップをビルドと分けて置いてください。
同じ理由でemitDecoratorMetadataと.d.tsの生成にも対応しません。前者はデコレータへ型情報を埋め込む機能のため、型を見ないesbuildでは原理的に実現できない部分。NestJSのようにこのメタデータへ依存するフレームワークは、tscかSWCを併用する構成になります。加えてファイル単位で独立に変換する都合上、tsconfig.jsonではisolatedModulesとesModuleInteropを有効にしておくのが公式の推奨です。
esbuildが読むtsconfigの項目とデコレータの対応範囲
tsconfig.jsonは全項目が読まれるわけではありません。esbuildが参照するのはtarget、baseUrl、paths、experimentalDecorators、useDefineForClassFields、verbatimModuleSyntax、JSX関連の各項目などに限られます。ここに載っていない項目は無視されるため、tscでは通る設定がesbuild経由では効かない、という食い違いが起きます。
デコレータはexperimentalDecoratorsの有無で挙動が変わります。有効ならTypeScript従来のデコレータとして、無効ならJavaScript標準側の提案に沿った形で扱われる仕組み。もうひとつの落とし穴がuseDefineForClassFieldsで、targetがES2022より前だと既定値がfalseになり、クラスフィールドの意味が代入寄りに倒れます。既存コードを移すときは、この既定値の差で挙動が変わる箇所を先に洗い出してください。
CSSとCSSモジュールの標準対応とプラグインが必要になる場面
CSSはesbuildが第一級で扱う入力です。ベンダープレフィックスの付与、新しい構文を古いブラウザ向けへ落とす変換、そして.module.cssという拡張子によるCSSモジュールが標準で通ります。composesにも対応しており、JavaScript側からCSSをimportすると、対になるCSSファイルが並んで出力される仕組み。SassやTailwind CSSのような別言語や別ツールは範囲外で、プラグインか前段の処理が要ります。
ローダーは拡張子ごとの解釈を切り替える機能で、js、ts、tsx、jsx、css、global-css、local-css、json、text、base64、binary、dataurl、file、copy、emptyが用意されています。注意点がひとつ。tsxローダーは.tsファイルを処理できません。文法が衝突するためで、<T>() => {}のようなジェネリックなアロー関数がtsx側ではJSXと解釈されてしまいます。
Vite・webpack・SWCとの違い|esbuildを直接使う判断軸
選定の場面では、esbuildを単体で使うのか、別のツールの内側で間接的に使うのかが論点になります。ここは2026年時点の状況が数年前と変わっているため、古い記事の記述をそのまま持ち込まないでください。
Viteが内部でesbuildを使う関係と単体で採用する場合との差
「ViteはesbuildをTypeScript変換と依存の事前バンドルに使う」という説明は長く定説でした。ところが2026年8月1日時点のVite公式ドキュメント(v8.1.5系)を読むと、事前バンドルはRolldownが担い、TypeScriptとJSXの変換はOxc Transformerに置き換わっています。esbuildへの言及は、tsconfig.jsonのtarget値を無視する挙動を説明する箇所だけに縮んでいました。
つまり「Viteを使っているなら実質esbuildを使っている」という前提は、現在の版では成り立ちません。esbuildを自分のプロジェクトで使いたいなら、依存として明示的に入れて直接呼ぶ形になります。逆にViteの上でアプリを組むだけなら、esbuildの知識が必須という状況ではなくなりました。Viteを使ったReactプロジェクトのセットアップ手順や@vitejs/plugin-reactの設定と役割と読み比べると、担当範囲の違いが掴めます。
webpackやRollupと比べたときの機能差と速度差の内訳
webpackとRollupは、プラグイン生態系とコード分割の成熟度でesbuildを上回ります。webpackはローダーとプラグインの層が厚く、レガシーな構成の受け皿として今も現役。Rollupはライブラリのビルドで定番の位置にあり、出力の綺麗さと設定の見通しで支持されています。esbuildが勝つのは速度と導入の軽さで、公式は他のバンドラより10倍から100倍速いと表現しました。
| ツール | 実装言語 | 主な使いどころ |
|---|---|---|
| esbuild | Go | 社内ツール・関数バンドル |
| Rollup | JavaScript | ライブラリのビルド |
| webpack | JavaScript | 既存の大規模SPA |
| Turbopack | Rust | Next.jsの標準ビルド |
| SWC | Rust | 変換と圧縮の差し替え |
速度差の内訳を分けて捉えると判断を誤りません。解析と変換の速さは実装言語の差が素直に出る部分で、GoやRustの実装がJavaScript実装を引き離します。一方でコード分割の質、ツリーシェイキングの精度、プラグインで差し込める処理の幅は、速度とは別の軸。速いから乗り換える、ではなく、必要な機能が揃っているかを先に確認してください。
SWCやRust製ツールとの棲み分けと選定時に見るべき3つの観点
SWCはRust製の変換器で、バンドラというより変換と圧縮の差し替え部品として使われます。Next.jsの内部やJestの変換で採用されてきた経緯があり、esbuildとは守備範囲が重なりつつも用途が違う立ち位置。Rust製バンドラの側ではNext.js 16で既定になったTurbopackやFarm(farm-fe)とViteやRspackとの違いが比較の材料になります。
選定で見るべき観点は3つに絞れます。1つ目、フレームワークが決まっているか。Next.jsならTurbopack、Vue系ならViteというように、フレームワーク側の既定が答えを決めてしまう場面が多くあります。2つ目、成果物がアプリかライブラリか。3つ目、型検査とデコレータへの依存度です。この3点を先に埋めると、候補は自然に1つか2つへ絞られます。
受託開発でesbuildを採用してよい条件と見送るべき場面の整理
仕様の確認を踏まえて、案件でどう扱うかを言い切ります。ここは公式ドキュメントに書かれていない、現場側の判断です。
社内ツールやライブラリ配布でesbuildが噛み合う3つの条件
次の3条件が揃うなら、esbuild単体で進めて構いません。第一に、出力先がブラウザ向けの巨大なSPAではないこと。社内向けの管理画面、CLI、Lambdaなどの関数、npmで配るライブラリが該当します。第二に、フレームワーク固有の単一ファイルコンポーネントを使わないこと。第三に、型検査をCIの別ステップとして分離できる体制があること。
この条件で組むと、ビルド設定がJavaScriptの十数行に収まり、担当者が交代しても読み解ける状態を保てます。設定の総量が少ないこと自体が、保守の引き継ぎでは効いてくる利点。逆に言えば、設定量が増えて条件分岐が積み上がってきたら、それは土台を別のツールへ移す合図です。
大規模なSPAでesbuild単体の採用を見送る判断の分かれ目
見送りの判断は、次のいずれかに当たるかで決めてください。webpackプラグイン前提の社内基盤がある、ルート単位の細かいコード分割で初期表示を詰める要件がある、Vue・Svelte・Angularを使う、emitDecoratorMetadataに依存するサーバーフレームワークを使う。この4つのどれかに当たるなら、esbuild単体は無理筋です。
特に判断が割れやすいのがコード分割です。esbuildの分割はesm形式でのみ動き、公式自身が発展途上と認めている領域。初期表示の速度をルート単位で詰める要件があるなら、ViteやRollupやTurbopackを土台に据え、esbuildはその内部の変換部品として間接的に効かせる構成へ寄せてください。
移行や新規構築の見積もりに織り込むべき検証工数の具体的な見方
見積もりで見落としやすいのは、切り替え作業そのものより検証の工数です。型検査を外へ出す構成に変えるなら、CIのステップ追加とローカル手順の周知に工数が要ります。tsconfig.jsonのうちesbuildが読まない項目に依存していた箇所の洗い出しも、実際に動かすまで表に出てきません。
手順としては、まず現行のビルド設定をesbuildが読む項目と読まない項目へ仕分け、次に小さなエントリポイント1本で出力を比べ、最後に本番相当の構成へ広げる3段階が扱いやすい流れ。クラスフィールドの既定値差のように、ビルドは通るのに実行時だけ挙動が変わる不具合は自動テストで拾いにくく、主要画面の目視確認を工数へ織り込む必要があります。ビルド基盤の見直しを含むWebアプリの構築や改修は業務用・Webアプリ開発で対応しています。
esbuildの導入と運用について実装者から届く質問への回答
esbuildだけでTypeScriptプロジェクトをビルドできますか?
ビルド自体はできます。ただし型検査は行われないため、tscを別に走らせる前提が付きます。tsc --noEmitをCIのステップに置き、ビルドと型検査を分ける構成が定番。型定義ファイルを配布するライブラリなら、.d.tsの生成もtscか専用ツールで別途行ってください。
esbuildとViteはどちらを選べばよいですか?
アプリを開発するならVite、ビルド処理そのものを組み立てるならesbuildという分け方が実務的です。2026年時点のViteは内部の変換器をOxcへ、事前バンドルをRolldownへ移しているため、両者を「同じ系列のツール」と捉えないでください。
0.x系のまま本番で使って大丈夫でしょうか?
版を固定する運用とセットなら実務で使えます。公式が「後期ベータ」と書いている一方、ViteやAmazon CDKといった規模の大きいプロジェクトでの採用実績も併記されました。--save-exactで固定し、更新時は変更履歴を読んでから上げる手順を決めておけば、マイナー版の破壊的変更に不意を突かれる事態は避けられます。
webpackから乗り換えると本当に速くなりますか?
解析と変換の速度は上がります。ただしプラグインで補っていた処理を自前で書き直す工数が発生し、総量では相殺される場面も出てきました。判断の材料にするなら、キャッシュを消した状態同士で3回ずつ測り、中央値で比べてください。
プラグインはどこまで書けますか?
build APIに限って、ファイルの解決と読み込みへ割り込むプラグインを書けます。transform APIでは使えず、ブラウザで動かす同期版のAPIでも利用できません。ASTを触る公開APIは提供されていないため、コード変換を細かく制御したい要件はBabelやSWCなど別のツールへ回す判断になります。
関連記事
- Turbopackとは?Next.js 16で既定になったRust製バンドラの設定と移行判断:Next.js側の既定バンドラを確認できます
- Rollupとは|JavaScriptバンドラーのnpm導入から使い方・Webpack/Viteとの違いまで:バンドラーの基本動作を押さえられます
- Rust製ビルドツールFarm(farm-fe)とは?Vite・Rspackとの違いと使い方:Rust製ツールとの比較材料です
- Viteを使ったReactプロジェクトのセットアップ方法を徹底解説:Vite側の導入手順を確認できます
- SWCとは?Rust製コンパイラの設定と採用判断を実装目線で解説:.swcrcの書き方と型検査の運用が分かります
- @vitejs/plugin-react とは?v6(Vite 8・Babel廃止)の導入設定と plugin-react-swc との違い【2026年最新】:Vite系プラグインの役割が掴めます