Skip to content

import Build from "/ja/snippets/cli/build.mdx";

Bun の高速ネイティブバンドラーは、bun build CLI コマンドまたは Bun.build() JavaScript API を介して使用できます。

概要

  • JS API: await Bun.build({ entrypoints, outdir })
  • CLI: bun build <entry> --outdir ./out
  • ウォッチ:--watch で増分リビルド
  • ターゲット:--target browser|bun|node
  • フォーマット:--format esm|cjs|iife(cjs/iife は実験的)

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './build',
});

CLI

bash
bun build ./index.tsx --outdir ./build

これは高速です。以下の数値は、esbuild の three.js ベンチマーク でのパフォーマンスを表しています。

バンドルする理由

バンドラーは JavaScript エコシステムにおける重要なインフラストラクチャです。バンドルがなぜそれほど重要なのかの簡単な概要:

  • HTTP リクエストの削減node_modules 内の単一のパッケージは数百のファイルで構成されている可能性があり、大規模なアプリケーションにはそのような依存関係が数十あります。これらのファイルをそれぞれ個別の HTTP リクエストで読み込むことはすぐに実行不可能になるため、バンドラーはアプリケーションのソースコードを単一のリクエストで読み込める自己完結型の「バンドル」にまとめるために使用されます。
  • コード変換。モダンなアプリは TypeScript、JSX、CSS モジュールなどの言語やツールで構築されており、これらはすべてブラウザで消費される前にプレーンな JavaScript と CSS に変換する必要があります。これらの変換を設定するのがバンドラーの自然な場所です。
  • フレームワーク機能。フレームワークは、ファイルシステムルーティング、クライアント - サーバーコードの共存(getServerSideProps や Remix ローダーなど)、サーバーコンポーネントなどの一般的なパターンを実装するために、バンドラープラグインとコード変換に依存しています。
  • フルスタックアプリケーション。Bun のバンドラーは、サーバーコードとクライアントコードの両方を単一のコマンドで処理でき、最適化された本番ビルドと単一ファイルの実行可能ファイルを実現します。ビルド時 HTML インポートを使用すると、アプリケーション全体(フロントエンドアセットとバックエンドサーバー)を単一のデプロイ可能なユニットにバンドルできます。

バンドラー API について詳しく説明します。

NOTE

Bun バンドラーは、型チェックや型宣言の生成のために `tsc` を置き換えることを意図していません。

基本的な例

最初のバンドルを作成しましょう。次の 2 つのファイルがあり、これはシンプルなクライアントサイドレンダリング React アプリを実装しています。

tsx
import * as ReactDOM from "react-dom/client";
import { Component } from "./Component";

const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(<Component message="Sup!" />);
tsx
export function Component(props: { message: string }) {
  return <h1>{props.message}</h1>;
}

ここで、index.tsx はアプリケーションの「エントリーポイント」です。一般的に、これはサーバーの起動や、この場合のように React ルートの初期化などの副作用を実行するスクリプトです。TypeScript と JSX を使用しているため、ブラウザに送信する前にコードをバンドルする必要があります。

バンドルを作成するには:

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
});
bash
bun build ./index.tsx --outdir ./out

entrypoints で指定された各ファイルについて、Bun は新しいバンドルを生成します。このバンドルは、現在のワーキングディレクトリから解決された ./out ディレクトリにディスクに書き込まれます。ビルドを実行した後、ファイルシステムは次のようになります:

text
.
├── index.tsx
├── Component.tsx
└── out
    └── index.js

out/index.js の内容は次のようになります:

js
// out/index.js
// ...
// ~20k 行のコード
// `react-dom/client` の内容とそのすべての依存関係を含む
// $jsxDEV および $createRoot 関数が定義されている場所

// Component.tsx
function Component(props) {
  return $jsxDEV(
    "p",
    {
      children: props.message,
    },
    undefined,
    false,
    undefined,
    this,
  );
}

// index.tsx
var rootNode = document.getElementById("root");
var root = $createRoot(rootNode);
root.render(
  $jsxDEV(
    Component,
    {
      message: "Sup!",
    },
    undefined,
    false,
    undefined,
    this,
  ),
);

ウォッチモード

ランタイムとテストランナーと同様に、バンドラーはネイティブにウォッチモードをサポートしています。

bash
bun build ./index.tsx --outdir ./out --watch

コンテンツタイプ

Bun ランタイムと同様に、バンドラーはデフォルトでさまざまなファイルタイプをサポートしています。以下の表は、バンドラーの標準「ローダー」のセットをまとめたものです。完全なドキュメントについては、バンドラー > ファイルタイプ を参照してください。

拡張子詳細
.js .jsx .cjs .mjs .mts .cts .ts .tsxBun の組み込みトランスパイラーを使用してファイルを解析し、TypeScript/JSX 構文をバニラ JavaScript にトランスパイルします。バンドラーは、デッドコード削除とツリーシェイクを含む一連のデフォルト変換を実行します。現時点では、Bun は構文をダウングレードしようとしません。最近の ECMAScript 構文を使用すると、それがバンドルコードに反映されます。
.jsonJSON ファイルは解析され、JavaScript オブジェクトとしてバンドルにインライン化されます。

js<br/>import pkg from "./package.json";<br/>pkg.name; // => "my-package"<br/>
.jsoncコメント付き JSON。ファイルは解析され、JavaScript オブジェクトとしてバンドルにインライン化されます。

js<br/>import config from "./config.jsonc";<br/>config.name; // => "my-config"<br/>
.tomlTOML ファイルは解析され、JavaScript オブジェクトとしてバンドルにインライン化されます。

js<br/>import config from "./bunfig.toml";<br/>config.logLevel; // => "debug"<br/>
.yaml .ymlYAML ファイルは解析され、JavaScript オブジェクトとしてバンドルにインライン化されます。

js<br/>import config from "./config.yaml";<br/>config.name; // => "my-app"<br/>
.txtテキストファイルの内容が読み取られ、文字列としてバンドルにインライン化されます。

js<br/>import contents from "./file.txt";<br/>console.log(contents); // => "Hello, world!"<br/>
.htmlHTML ファイルが処理され、参照されているアセット(スクリプト、スタイルシート、画像)がバンドルされます。
.cssCSS ファイルはバンドルされ、出力ディレクトリ内の単一の .css ファイルにまとめられます。
.node .wasmこれらのファイルは Bun ランタイムでサポートされていますが、バンドル中はアセットとして扱われます。

アセット

バンドラーが認識できない拡張子のインポートを検出した場合、インポートされたファイルを外部ファイルとして扱います。参照されたファイルはそのまま outdir にコピーされ、インポートはファイルへのパスとして解決されます。

ts
// バンドルエントリーポイント
import logo from "./logo.svg";
console.log(logo);
ts
// バンドル出力
var logo = "./logo-a7305bdef.svg";
console.log(logo);

ファイルローダーの正確な動作は、namingpublicPath によっても影響を受けます。

プラグイン

この表で説明されている動作は、プラグインでオーバーライドまたは拡張できます。完全なドキュメントについては、バンドラー > ローダー ページを参照してください。

API

entrypoints

アプリケーションのエントリーポイントに対応するパスの配列。各エントリーポイントに対して 1 つのバンドルが生成されます。

JavaScript

ts
const result = await Bun.build({
  entrypoints: ["./index.ts"]
});

CLI

bash
bun build ./index.ts

outdir

出力ファイルが書き込まれるディレクトリ。

JavaScript

ts
const result = await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out'
});
// => { success: boolean, outputs: `BuildArtifact[]`, logs: `BuildMessage[]` }

CLI

bash
bun build ./index.ts --outdir ./out

JavaScript API に outdir が渡されない場合、バンドルされたコードはディスクに書き込まれません。バンドルされたファイルは BuildArtifact オブジェクトの配列として返されます。これらのオブジェクトは追加のプロパティを持つ Blob です。完全なドキュメントについては Outputs を参照してください。

ts
const result = await Bun.build({
  entrypoints: ["./index.ts"],
});

for (const res of result.outputs) {
  // Blob として処理可能
  await res.text();

  // Bun は Content-Type と Etag ヘッダーを設定します
  new Response(res);

  // 手動で書き込み可能ですが、この場合は `outdir` を使用するべきです。
  Bun.write(path.join("out", res.path), res);
}

outdir が設定されている場合、BuildArtifactpath プロパティは書き込まれた場所への絶対パスになります。

target

バンドルの意図された実行環境。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out',
  target: 'browser', // デフォルト
})

CLI

bash
bun build ./index.ts --outdir ./out --target browser

ターゲットに応じて、Bun は異なるモジュール解決ルールと最適化を適用します。

デフォルト。ブラウザでの実行を目的としたバンドルを生成するために使用されます。インポートの解決時に "browser" エクスポート条件を優先します。node:eventsnode:path などの組み込みモジュールをインポートすることは機能しますが、fs.readFile などの一部の関数を呼び出すことは機能しません。

Bun ランタイムで実行されることを目的としたバンドルを生成するために使用されます。多くの場合、サーバーサイドコードをバンドルする必要はありません。ソースコードを直接変更せずに実行できます。ただし、サーバーコードをバンドルすると、起動時間が短縮され、実行パフォーマンスが向上します。これは、サーバーコードとクライアントコードの両方を一緒にバンドルする、ビルド時 HTML インポートを使用したフルスタックアプリケーションの構築に使用するターゲットです。

target: "bun" で生成されたすべてのバンドルには、特別な // @bun プラグマがマークされており、これは Bun ランタイムに対して、実行前にファイルを再トランスパイルする必要がないことを示します。

エントリーポイントに Bun shebang(#!/usr/bin/env bun)が含まれている場合、バンドラーはデフォルトで "browser" ではなく target: "bun" を使用します。

target: "bun"format: "cjs" を一緒に使用すると、// @bun @bun-cjs プラグマが追加され、CommonJS ラッパー関数は Node.js と互換性がありません。

Node.js で実行されることを目的としたバンドルを生成するために使用されます。インポートの解決時に "node" エクスポート条件を優先し、.mjs を出力します。将来的には、Bun グローバルとその他の組み込み bun:* モジュールを自動的にポリフィルしますが、これはまだ実装されていません。

format

生成されたバンドルで使用するモジュールフォーマットを指定します。

Bun はデフォルトで "esm" を使用し、"cjs""iife" の実験的サポートを提供します。

format: "esm" - ES モジュール

これはデフォルトのフォーマットで、トップレベル await、import.meta などを含む ES モジュール構文をサポートします。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  format: "esm",
})

CLI

bash
bun build ./index.tsx --outdir ./out --format esm

ES モジュール構文をブラウザで使用するには、format"esm" に設定し、<script type="module"> タグに type="module" が設定されていることを確認してください。

format: "cjs" - CommonJS

CommonJS モジュールをビルドするには、format"cjs" に設定します。"cjs" を選択すると、デフォルトのターゲットが "browser"(esm)から "node"(cjs)に変更されます。format: "cjs"target: "node" でトランスパイルされた CommonJS モジュールは、Bun と Node.js の両方で実行できます(使用されている API が両方でサポートされている場合)。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  format: "cjs",
})

CLI

bash
bun build ./index.tsx --outdir ./out --format cjs

format: "iife" - IIFE

TODO: globalNames をサポートしたら IIFE をドキュメント化します。

jsx

JSX 変換の動作を設定します。JSX のコンパイル方法を細かく制御できます。

クラシックランタイムの例factoryfragment を使用):

ts
await Bun.build({
  entrypoints: ["./app.tsx"],
  outdir: "./out",
  jsx: {
    factory: "h",
    fragment: "Fragment",
    runtime: "classic",
  },
});
bash
# JSX 設定は bunfig.toml または tsconfig.json で処理されます
bun build ./app.tsx --outdir ./out

オートマチックランタイムの例importSource を使用):

ts
await Bun.build({
  entrypoints: ["./app.tsx"],
  outdir: "./out",
  jsx: {
    importSource: "preact",
    runtime: "automatic",
  },
});
bash
# JSX 設定は bunfig.toml または tsconfig.json で処理されます
bun build ./app.tsx --outdir ./out

splitting

コード分割を有効にするかどうか。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  splitting: false, // デフォルト
})

CLI

bash
bun build ./index.tsx --outdir ./out --splitting

true の場合、バンドラーはコード分割を有効にします。複数のエントリーポイントが同じファイル、モジュール、またはファイル/モジュールのセットをインポートする場合、共有コードを別のバンドルに分割すると便利なことがあります。この共有バンドルはチャンクとして知られています。次のファイルを考慮してください:

ts
import { shared } from "./shared.ts";
ts
import { shared } from "./shared.ts";
ts
export const shared = "shared";

コード分割を有効にして entry-a.tsentry-b.ts をバンドルするには:

JavaScript

ts
await Bun.build({
  entrypoints: ['./entry-a.ts', './entry-b.ts'],
  outdir: './out',
  splitting: true,
})

CLI

bash
bun build ./entry-a.ts ./entry-b.ts --outdir ./out --splitting

このビルドを実行すると、次のファイルが生成されます:

text
.
├── entry-a.tsx
├── entry-b.tsx
├── shared.tsx
└── out
    ├── entry-a.js
    ├── entry-b.js
    └── chunk-2fce6291bf86559d.js

生成された chunk-2fce6291bf86559d.js ファイルには共有コードが含まれています。衝突を避けるために、ファイル名にはデフォルトでコンテンツハッシュが自動的に含まれています。これは naming でカスタマイズできます。

plugins

バンドル中に使用するプラグインのリスト。

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
  plugins: [
    /* ... */
  ],
});

Bun は Bun のランタイムとバンドラーの両方のためにユニバーサルプラグインシステムを実装しています。完全なドキュメントについては、プラグインのドキュメント を参照してください。

env

バンドル中の環境変数の処理方法を制御します。内部的には、define を使用して環境変数をバンドルに注入しますが、注入する環境変数を指定しやすくします。

env: "inline"

process.env.FOO 参照を実際の環境変数の値を含む文字列リテラルに変換することにより、環境変数をバンドル出力に注入します。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  env: "inline",
})

CLI

bash
bun build ./index.tsx --outdir ./out --env inline

以下の入力の場合:

js
// input.js
console.log(process.env.FOO);
console.log(process.env.BAZ);

生成されたバンドルには次のコードが含まれます:

js
// output.js
console.log("bar");
console.log("123");

env: "PUBLIC_*"(プレフィックス)

指定されたプレフィックス(* 文字の前の部分)に一致する環境変数をインライン化し、process.env.FOO を実際の環境変数の値に置き換えます。これは、公開 URL やクライアントサイドトークンのようなものの環境変数を選択的にインライン化するために役立ち、出力バンドルにプライベートな認証情報を注入する心配がありません。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  
  // "ACME_PUBLIC_" で始まるすべての環境変数をインライン化
  env: "ACME_PUBLIC_*",
})

CLI

bash
bun build ./index.tsx --outdir ./out --env ACME_PUBLIC_*

例えば、次の環境変数が与えられた場合:

bash
FOO=bar BAZ=123 ACME_PUBLIC_URL=https://acme.com

そしてソースコード:

tsx
console.log(process.env.FOO);
console.log(process.env.ACME_PUBLIC_URL);
console.log(process.env.BAZ);

生成されたバンドルには次のコードが含まれます:

js
console.log(process.env.FOO);
console.log("https://acme.com");
console.log(process.env.BAZ);

env: "disable"

環境変数の注入を完全に無効にします。

sourcemap

生成するソースマップのタイプを指定します。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  sourcemap: 'linked', // デフォルト 'none'
})

CLI

bash
bun build ./index.tsx --outdir ./out --sourcemap linked
説明
"none"デフォルト。ソースマップは生成されません。
"linked"*.js バンドルと一緒に、//# sourceMappingURL コメントで 2 つをリンクする別々の *.js.map ファイルが作成されます。--outdir を設定する必要があります。これのベース URL は --public-path でカスタマイズできます。

js<br/>// <ここにバンドルコード><br/><br/>//# sourceMappingURL=bundle.js.map<br/>
"external"//# sourceMappingURL コメントを挿入せずに、各 *.js バンドルと一緒に別々の *.js.map ファイルが作成されます。

生成されたバンドルには、バンドルを対応するソースマップに関連付けるために使用できるデバッグ ID が含まれています。この debugId はファイルの下部にコメントとして追加されます。

js<br/>// <生成されたバンドルコード><br/><br/>//# debugId=<デバッグ ID><br/>
"inline"ソースマップが生成され、base64 ペイロードとして生成されたバンドルの末尾に追加されます。

js<br/>// <ここにバンドルコード><br/><br/>//# sourceMappingURL=data:application/json;base64,<エンコードされたソースマップ><br/>

関連する *.js.map ソースマップは、同等の debugId プロパティを含む JSON ファイルになります。

minify

ミニファイを有効にするかどうか。デフォルトは false

NOTE

`bun` をターゲットにする場合、識別子はデフォルトでミニファイされます。

すべてのミニファイオプションを有効にするには:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  minify: true, // デフォルト false
})

CLI

```bash
bun build ./index.tsx --outdir ./out --minify
```

特定のミニファイを細かく有効にするには:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  minify: {
    whitespace: true,
    identifiers: true,
    syntax: true,
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out --minify-whitespace --minify-identifiers --minify-syntax

external

外部として扱うインポートパスのリスト。デフォルトは []

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ["lodash", "react"], // デフォルト:[]
})

CLI

bash
bun build ./index.tsx --outdir ./out --external lodash --external react

外部インポートとは、最終バンドルに含まれないインポートです。代わりに、インポート文はそのまま残され、ランタイムに解決されます。

例えば、次のエントリーポイントファイルを考慮してください:

tsx
import _ from "lodash";
import { z } from "zod";

const value = z.string().parse("Hello world!");
console.log(_.upperCase(value));

通常、index.tsx をバンドルすると「zod」パッケージのソースコード全体を含むバンドルが生成されます。代わりにインポート文をそのまま残したい場合は、外部としてマークできます:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ['zod'],
})

CLI

bash
bun build ./index.tsx --outdir ./out --external zod

生成されたバンドルは次のようになります:

js
import { z } from "zod";

// ...
// "lodash" パッケージの内容
// `_.upperCase` 関数を含む

var value = z.string().parse("Hello world!");
console.log(_.upperCase(value));

すべてのインポートを外部としてマークするには、ワイルドカード * を使用します:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ['*'],
})

CLI

bash
bun build ./index.tsx --outdir ./out --external '*'

packages

パッケージ依存関係をバンドルに含めるかどうかを制御します。可能な値:bundle(デフォルト)、external。Bun は、パスが .../ で始まらないインポートをパッケージとして扱います。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.ts'],
  packages: 'external',
})

CLI

bash
bun build ./index.ts --packages external

naming

生成されたファイル名をカスタマイズします。デフォルトは ./[dir]/[name].[ext]

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: "[dir]/[name].[ext]", // デフォルト
})

CLI

bash
bun build ./index.tsx --outdir ./out --entry-naming "[dir]/[name].[ext]"

デフォルトでは、生成されたバンドルの名前は関連するエントリーポイントの名前に基づいています。

text
.
├── index.tsx
└── out
    └── index.js

複数のエントリーポイントがある場合、生成されたファイル階層はエントリーポイントのディレクトリ構造を反映します。

text
.
├── index.tsx
└── nested
    └── index.tsx
└── out
    ├── index.js
    └── nested
        └── index.js

生成されたファイルの名前と場所は、naming フィールドでカスタマイズできます。このフィールドは、エントリーポイントに対応するすべてのバンドルのファイル名を生成するために使用されるテンプレート文字列を受け入れます。ここで、次のトークンは対応する値に置き換えられます:

  • [name] - 拡張子なしのエントリーポイントファイルの名前。
  • [ext] - 生成されたバンドルの拡張子。
  • [hash] - バンドルコンテンツのハッシュ。
  • [dir] - プロジェクトルートからソースファイルの親ディレクトリへの相対パス。

例えば:

トークン[name][ext][hash][dir]
./index.tsxindexjsa1b2c3d4"" (空文字列)
./nested/entry.tsentryjsc3d4e5f6"nested"

これらのトークンを組み合わせてテンプレート文字列を作成できます。例えば、生成されたバンドル名にハッシュを含めるには:

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: 'files/[dir]/[name]-[hash].[ext]',
})

CLI

bash
bun build ./index.tsx --outdir ./out --entry-naming 'files/[dir]/[name]-[hash].[ext]'

このビルドでは、次のファイル構造が生成されます:

text
.
├── index.tsx
└── out
    └── files
        └── index-a1b2c3d4.js

naming フィールドに文字列が提供される場合、これはエントリーポイントに対応するバンドルにのみ使用されます。チャンクとコピーされたアセットの名前は影響を受けません。JavaScript API を使用すると、生成された各ファイルタイプに対して個別のテンプレート文字列を指定できます。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: {
    // デフォルト値
    entry: '[dir]/[name].[ext]',
    chunk: '[name]-[hash].[ext]',
    asset: '[name]-[hash].[ext]',
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out \
  --entry-naming '[dir]/[name].[ext]' \
  --chunk-naming '[name]-[hash].[ext]' \
  --asset-naming '[name]-[hash].[ext]'

root

プロジェクトのルートディレクトリ。

JavaScript

ts
await Bun.build({
  entrypoints: ['./pages/a.tsx', './pages/b.tsx'],
  outdir: './out',
  root: '.',
})

CLI

bash
bun build ./pages/a.tsx ./pages/b.tsx --outdir ./out --root .

指定しない場合、すべてのエントリーポイントファイルの最初の共通祖先として計算されます。次のファイル構造を考慮してください:

text
.
└── pages
  └── index.tsx
  └── settings.tsx

pages ディレクトリ内の両方のエントリーポイントをビルドできます:

JavaScript

js
await Bun.build({
  entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
  outdir: './out',
})

CLI

bash
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./out

これにより、次のようなファイル構造になります:

text
.
└── pages
  └── index.tsx
  └── settings.tsx
└── out
  └── index.js
  └── settings.js

pages ディレクトリはエントリーポイントファイルの最初の共通祖先であるため、プロジェクトルートと見なされます。これは、生成されたバンドルが out ディレクトリのトップレベルにあることを意味します。out/pages ディレクトリはありません。

この動作は、root オプションを指定することでオーバーライドできます:

JavaScript

js
await Bun.build({
  entrypoints: ['./pages/index.tsx', './pages/settings.tsx'],
  outdir: './out',
  root: '.',
})

CLI

bash
bun build ./pages/index.tsx ./pages/settings.tsx --outdir ./out --root .

.root として指定すると、生成されたファイル構造は次のようになります:

.
└── pages
  └── index.tsx
  └── settings.tsx
└── out
  └── pages
    └── index.js
    └── settings.js

publicPath

バンドルコード内のインポートパスに追加されるプレフィックス。

多くの場合、生成されたバンドルにはインポート文が含まれません。結局のところ、バンドルの目的はすべてのコードを 1 つのファイルに結合することです。ただし、生成されたバンドルにインポート文が含まれるケースがいくつかあります。

  • アセットインポート*.svg のような認識されていないファイルタイプをインポートすると、バンドラーはファイルローダーに委ね、ファイルをそのまま outdir にコピーします。インポートは変数に変換されます
  • 外部モジュール — ファイルとモジュールは外部としてマークでき、その場合それらはバンドルに含まれません。代わりに、インポート文は最終バンドルに残されます。
  • チャンキングsplitting が有効な場合、バンドラーは複数のエントリーポイント間で共有されるコードを表す別の「チャンク」ファイルを生成する可能性があります。

これらのケースのいずれかでは、最終バンドルに他のファイルへのパスが含まれる可能性があります。デフォルトでは、これらのインポートは相対パスです。これはシンプルなアセットインポートの例です:

ts
import logo from "./logo.svg";
console.log(logo);
ts
var logo = "./logo-a7305bdef.svg";
console.log(logo);

publicPath を設定すると、指定された値ですべてのファイルパスがプレフィックスされます。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  publicPath: 'https://cdn.example.com/', // デフォルトは未定義
})

CLI

bash
bun build ./index.tsx --outdir ./out --public-path 'https://cdn.example.com/'

出力ファイルは次のようになります:

js
var logo = "https://cdn.example.com/logo-a7305bdef.svg";

define

ビルド時に置き換えられるグローバル識別子のマップ。このオブジェクトのキーは識別子名で、値はインライン化される JSON 文字列です。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  define: {
    STRING: JSON.stringify("value"),
    "nested.boolean": "true",
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out --define STRING='"value"' --define nested.boolean=true

loader

ファイル拡張子から組み込みローダー名へのマップ。これは、特定のファイルの読み込み方法をすばやくカスタマイズするために使用できます。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  loader: {
    ".png": "dataurl",
    ".txt": "file",
  },
})

CLI

bash
bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:file

最終バンドルに追加されるバナー。これは React の use client のようなディレクティブや、コードのライセンスなどのコメントブロックです。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  banner: 'use client;'
})

CLI

bash
bun build ./index.tsx --outdir ./out --banner 'use client";'

最終バンドルに追加されるフッター。これはライセンスのコメントブロックや楽しいイースターエッグです。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  footer: '// built with love in SF'
})

CLI

bash
bun build ./index.tsx --outdir ./out --footer '// built with love in SF'

drop

バンドルから関数呼び出しを削除します。例えば、--drop=consoleconsole.log へのすべての呼び出しを削除します。引数も削除されます。それらの引数が副作用を持つ可能性があっても関係ありません。debugger をドロップすると、すべての debugger 文が削除されます。

JavaScript

ts
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  drop: ["console", "debugger", "anyIdentifier.or.propertyAccess"],
})

CLI

bash
bun build ./index.tsx --outdir ./out --drop console --drop debugger

Outputs

Bun.build 関数は Promise<BuildOutput> を返します。これは次のように定義されています:

ts
interface BuildOutput {
  outputs: BuildArtifact[];
  success: boolean;
  logs: Array<object>; // 詳細はドキュメントを参照
}

interface BuildArtifact extends Blob {
  kind: "entry-point" | "chunk" | "asset" | "sourcemap";
  path: string;
  loader: Loader;
  hash: string | null;
  sourcemap: BuildArtifact | null;
}

outputs 配列には、ビルドによって生成されたすべてのファイルが含まれます。各アーティファクトは Blob インターフェースを実装します。

ts
const build = await Bun.build({
  /* */
});

for (const output of build.outputs) {
  await output.arrayBuffer(); // => ArrayBuffer
  await output.bytes(); // => Uint8Array
  await output.text(); // string
}

各アーティファクトには、次のプロパティも含まれています:

プロパティ説明
kindこのファイルがどの種類のビルド出力か。ビルドは、バンドルされたエントリーポイント、コード分割「チャンク」、ソースマップ、バイトコード、コピーされたアセット(画像など)を生成します。
pathディスク上のファイルへの絶対パス
loaderファイルの解釈に使用されたローダー。Bun がファイル拡張子を適切な組み込みローダーにマッピングする方法については、バンドラー > ローダー を参照してください。
hashファイルコンテンツのハッシュ。アセットの場合は常に定義されます。
sourcemap生成された場合、このファイルに対応するソースマップファイル。エントリーポイントとチャンクに対してのみ定義されます。

BunFile と同様に、BuildArtifact オブジェクトは new Response() に直接渡すことができます。

ts
const build = await Bun.build({
  /* */
});

const artifact = build.outputs[0];

// Content-Type ヘッダーは自動的に設定されます
return new Response(artifact);

Bun ランタイムは、デバッグを容易にするために BuildArtifact オブジェクトの特別なpretty-print を実装しています。

ts
// build.ts
const build = await Bun.build({
  /* */
});

const artifact = build.outputs[0];
console.log(artifact);
bash
bun run build.ts

BuildArtifact (entry-point) {
  path: "./index.js",
  loader: "tsx",
  kind: "entry-point",
  hash: "824a039620219640",
  Blob (74756 bytes) {
    type: "text/javascript;charset=utf-8"
  },
  sourcemap: BuildArtifact (sourcemap) {
    path: "./index.js.map",
    loader: "file",
    kind: "sourcemap",
    hash: "e7178cda3e72e301",
    Blob (24765 bytes) {
      type: "application/json;charset=utf-8"
    },
    sourcemap: null
  }
}

Bytecode

bytecode: boolean オプションを使用して、JavaScript/TypeScript エントリーポイントのバイトコードを生成できます。これにより、大規模なアプリケーションの起動時間を大幅に短縮できます。"cjs" フォーマットのみサポートされ、"target": "bun" のみをサポートし、Bun の一致するバージョンに依存します。これにより、各エントリーポイントに対応する .jsc ファイルが追加されます。

JavaScript

ts
await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
  bytecode: true,
})

CLI

bash
bun build ./index.tsx --outdir ./out --bytecode

実行可能ファイル

Bun は、JavaScript/TypeScript エントリーポイントをスタンドアロンの実行可能ファイルに「コンパイル」することをサポートしています。この実行可能ファイルには、Bun バイナリのコピーが含まれています。

bash
bun build ./cli.tsx --outfile mycli --compile
./mycli

完全なドキュメントについては、バンドラー > 実行可能ファイル を参照してください。

ログとエラー

失敗時、Bun.buildAggregateError で拒否されたプロミスを返します。これは、エラーリストのきれいな出力のためにコンソールにログ出力するか、try/catch ブロックでプログラム的に読み取ることができます。

ts
try {
  const result = await Bun.build({
    entrypoints: ["./index.tsx"],
    outdir: "./out",
  });
} catch (e) {
  // TypeScript では catch 句のアノテーションは許可されていません
  const error = e as AggregateError;
  console.error("Build Failed");

  // 例:組み込みフォーマッターの使用
  console.error(error);

  // 例:失敗を JSON 文字列としてシリアライズ
  console.error(JSON.stringify(error, null, 2));
}

ほとんどの場合、Bun はキャッチされない例外をきれいに出力するため、明示的な try/catch は必要ありません。Bun.build 呼び出しでトップレベル await を使用するだけで十分です。

error.errors 内の各アイテムは BuildMessage または ResolveMessageError のサブクラス)のインスタンスで、各エラーに関する詳細情報が含まれています。

ts
class BuildMessage {
  name: string;
  position?: Position;
  message: string;
  level: "error" | "warning" | "info" | "debug" | "verbose";
}

class ResolveMessage extends BuildMessage {
  code: string;
  referrer: string;
  specifier: string;
  importKind: ImportKind;
}

ビルド成功時、返されたオブジェクトには logs プロパティが含まれており、これにはバンドラーの警告と情報メッセージが含まれています。

ts
const result = await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
});

if (result.logs.length > 0) {
  console.warn("Build succeeded with warnings:");
  for (const message of result.logs) {
    // Bun はメッセージオブジェクトをきれいに出力します
    console.warn(message);
  }
}

リファレンス

ts
interface Bun {
  build(options: BuildOptions): Promise<BuildOutput>;
}

interface BuildConfig {
  entrypoints: string[]; // ファイルパスのリスト
  outdir?: string; // 出力ディレクトリ
  target?: Target; // デフォルト:"browser"
  /**
   * 出力モジュールフォーマット。トップレベル await は `"esm"` のみでサポートされています。
   *
   * 可能:
   * - `"esm"`
   * - `"cjs"`(**実験的**)
   * - `"iife"`(**実験的**)
   *
   * @default "esm"
   */
  format?: "esm" | "cjs" | "iife";
  /**
   * JSX 変換の動作を制御するための JSX 設定オブジェクト
   */
  jsx?: {
    runtime?: "automatic" | "classic";
    importSource?: string;
    factory?: string;
    fragment?: string;
    sideEffects?: boolean;
    development?: boolean;
  };
  naming?:
    | string
    | {
        chunk?: string;
        entry?: string;
        asset?: string;
      };
  root?: string; // プロジェクトルート
  splitting?: boolean; // デフォルト true、コード分割を有効
  plugins?: BunPlugin[];
  external?: string[];
  packages?: "bundle" | "external";
  publicPath?: string;
  define?: Record<string, string>;
  loader?: { [k in string]: Loader };
  sourcemap?: "none" | "linked" | "inline" | "external" | boolean; // デフォルト:"none"、true -> "inline"
  /**
   * インポート解決時に使用される package.json `exports` 条件
   *
   * `bun build` または `bun run` の `--conditions` と同等。
   *
   * https://nodejs.org/api/packages.html#exports
   */
  conditions?: Array<string> | string;

  /**
   * バンドル中の環境変数の処理方法を制御します。
   *
   * 可能:
   * - `"inline"`: `process.env.FOO` 参照を実際の環境変数の値を含む文字列リテラルに変換することにより、環境変数をバンドル出力に注入
   * - `"disable"`: 環境変数の注入を完全に無効
   * - `*` で終わる文字列:指定されたプレフィックスに一致する環境変数をインライン化。
   *   例:"MY_PUBLIC_*" は "MY_PUBLIC_" で始まる環境変数のみを含めます
   */
  env?: "inline" | "disable" | `${string}*`;
  minify?:
    | boolean
    | {
        whitespace?: boolean;
        syntax?: boolean;
        identifiers?: boolean;
      };
  /**
   * @__PURE__ や package.json "sideEffects" フィールドなどのデッドコード削除/ツリーシェイク注釈を無視します。
   * これは、ライブラリ内の不正確な注釈に対する一時的な回避策としてのみ使用するべきです。
   */
  ignoreDCEAnnotations?: boolean;
  /**
   * minify.whitespace が true でも @__PURE__ 注釈を強制的に出力します。
   */
  emitDCEAnnotations?: boolean;

  /**
   * 出力のバイトコードを生成します。これにより、コールドスタート時間が大幅に短縮されますが、
   * 最終出力が大きくなり、メモリ使用量がわずかに増加します。
   *
   * バイトコードは現在 CommonJS(`format: "cjs"`)のみでサポートされています。
   *
   * `target: "bun"` である必要があります
   * @default false
   */
  bytecode?: boolean;
  /**
   * "use client"; のようなバナーをバンドルコードに追加します
   */
  banner?: string;
  /**
   * コメントブロックのようなフッターをバンドルコードに追加します
   *
   * `// made with bun!`
   */
  footer?: string;

  /**
   * 一致するプロパティアクセスへの関数呼び出しを削除します。
   */
  drop?: string[];

  /**
   * - `true` に設定すると、ビルド失敗時に AggregateError で拒否されたプロミスを返します
   * - `false` に設定すると、`{success: false}` の {@link BuildOutput} を返します
   *
   * @default true
   */
  throw?: boolean;

  /**
   * パス解決に使用するカスタム tsconfig.json ファイルパス。
   * CLI の `--tsconfig-override` と同等。
   */
  tsconfig?: string;

  outdir?: string;
}

interface BuildOutput {
  outputs: BuildArtifact[];
  success: boolean;
  logs: Array<BuildMessage | ResolveMessage>;
}

interface BuildArtifact extends Blob {
  path: string;
  loader: Loader;
  hash: string | null;
  kind: "entry-point" | "chunk" | "asset" | "sourcemap" | "bytecode";
  sourcemap: BuildArtifact | null;
}

type Loader =
  | "js"
  | "jsx"
  | "ts"
  | "tsx"
  | "css"
  | "json"
  | "jsonc"
  | "toml"
  | "yaml"
  | "text"
  | "file"
  | "napi"
  | "wasm"
  | "html";

interface BuildOutput {
  outputs: BuildArtifact[];
  success: boolean;
  logs: Array<BuildMessage | ResolveMessage>;
}

declare class ResolveMessage {
  readonly name: "ResolveMessage";
  readonly position: Position | null;
  readonly code: string;
  readonly message: string;
  readonly referrer: string;
  readonly specifier: string;
  readonly importKind:
    | "entry_point"
    | "stmt"
    | "require"
    | "import"
    | "dynamic"
    | "require_resolve"
    | "at"
    | "at_conditional"
    | "url"
    | "internal";
  readonly level: "error" | "warning" | "info" | "debug" | "verbose";

  toString(): string;
}

Bun by www.bunjs.com.cn 編集