Bun

vs esbuild

Bun 的 bundler API 主要受到 esbuild 的啟發。從 esbuild 遷移到 Bun 的 bundler 應該相對容易。本指南將簡要說明您可能考慮遷移到 Bun 的 bundler 的原因,並提供一個並排的 API 比較參考,供已熟悉 esbuild 的 API 的人使用。

有一些行為差異需要注意。

  • 預設打包。與 esbuild 不同,Bun 預設總是打包。這就是為什麼在 Bun 範例中不需要 --bundle 旗標。若要個別轉譯每個檔案,請使用 Bun.Transpiler
  • 它只是一個 bundler。與 esbuild 不同,Bun 的 bundler 不包含內建的開發伺服器或檔案監控器。它只是一個 bundler。bundler 旨在與 Bun.serve 和其他執行時期 API 結合使用,以達到相同的效果。因此,所有與 HTTP/檔案監控相關的選項都不適用。

效能

Bun 的 bundler 結合了效能導向的 API,以及高度最佳化的基於 Zig 的 JS/TS 解析器,在 esbuild 的 three.js 基準測試 中,比 esbuild 快 1.75 倍。

從頭開始打包 10 份 three.js,並包含原始碼對應和縮小

CLI API

Bun 和 esbuild 都提供命令列介面。

esbuild <entrypoint> --outdir=out --bundle
bun build <entrypoint> --outdir=out

在 Bun 的 CLI 中,像 --minify 這樣的簡單布林旗標不接受參數。像 --outdir <path> 這樣的其他旗標接受參數;這些旗標可以寫成 --outdir out--outdir=out。某些旗標,例如 --define,可以指定多次:--define foo=bar --define bar=baz

esbuildbun build
--bundlen/aBun 總是會打包,使用 --no-bundle 來停用此行為。

--define:K=V

--define K=V

語法差異小;沒有冒號。

esbuild --define:foo=bar
bun build --define foo=bar

--external:<pkg>

--external <pkg>

語法差異小;沒有冒號。

esbuild --external:react
bun build --external react
--format--formatBun 目前僅支援 "esm",但已規劃其他模組格式。esbuild 預設為 "iife"

--loader:.ext=loader

--loader .ext:loader

Bun 支援與 esbuild 不同的內建載入器組;請參閱 Bundler > Loaders 以取得完整參考。esbuild 載入器 dataurlbinarybase64copyempty 尚未實作。

--loader 的語法略有不同。

esbuild app.ts --bundle --loader:.svg=text
bun build app.ts --loader .svg:text
--minify--minify沒有差異
--outdir--outdir沒有差異
--outfile--outfile
--packagesn/a不支援
--platform--target為了一致性,重新命名為 --target,與 tsconfig 一致。不支援 neutral
--serven/a不適用
--sourcemap--sourcemap沒有差異
--splitting--splitting沒有差異
--targetn/a不支援。Bun 的打包器目前不執行語法降級。
--watch--watch沒有差異
--allow-overwriten/a永遠不允許覆寫
--analyzen/a不支援
--asset-names--asset-naming為了一致性,重新命名為 JS API 中的 naming
--bannern/a不支援
--certfilen/a不適用
--charset=utf8n/a不支援
--chunk-names--chunk-naming為了一致性,重新命名為 JS API 中的 naming
--colorn/a總是啟用
--dropn/a不支援
--entry-names--entry-naming為了一致性,重新命名為 JS API 中的 naming
--footern/a不支援
--global-namen/a不適用,Bun 目前不支援 iife 輸出
--ignore-annotationsn/a不支援
--injectn/a不支援
--jsx--jsx-runtime <runtime>支援 "automatic"(使用 jsx 轉換)和 "classic"(使用 React.createElement
--jsx-devn/aBun 從 tsconfig.json 讀取 compilerOptions.jsx 以確定預設值。如果 compilerOptions.jsx"react-jsx",或如果 NODE_ENV=production,Bun 將使用 jsx 轉換。否則,它會使用 jsxDEV。對於任何 Bun 都使用 jsxDEV。打包器不支援 preserve
--jsx-factory--jsx-factory
--jsx-fragment--jsx-fragment
--jsx-import-source--jsx-import-source
--jsx-side-effectsn/aJSX 始終假設沒有副作用
--keep-namesn/a不支援
--keyfilen/a不適用
--legal-commentsn/a不支援
--log-leveln/a不支援。這可以在 bunfig.toml 中設定為 logLevel
--log-limitn/a不支援
--log-override:X=Yn/a不支援
--main-fieldsn/a不支援
--mangle-cachen/a不支援
--mangle-propsn/a不支援
--mangle-quotedn/a不支援
--metafilen/a不支援
--minify-whitespace--minify-whitespace
--minify-identifiers--minify-identifiers
--minify-syntax--minify-syntax
--out-extensionn/a不支援
--outbase--root
--preserve-symlinksn/a不支援
--public-path--public-path
--puren/a不支援
--reserve-propsn/a不支援
--resolve-extensionsn/a不支援
--servedirn/a不適用
--source-rootn/a不支援
--sourcefilen/a不支援。Bun 尚未支援 stdin 輸入。
--sourcemap--sourcemap沒有差異
--sources-contentn/a不支援
--supportedn/a不支援
--tree-shakingn/a永遠為 true
--tsconfig--tsconfig-override
--versionn/a執行 bun --version 以查看 Bun 的版本。

JavaScript API

esbuild.build()Bun.build()
absWorkingDirn/a永遠設定為 process.cwd()
aliasn/a不支援
allowOverwriten/a永遠為 false

assetNames

naming.asset

使用與 esbuild 相同的範本語法,但必須明確包含 [ext]

Bun.build({
  entrypoints: ["./index.tsx"],
  naming: {
    asset: "[name].[ext]",
  },
});
bannern/a不支援
bundlen/a永遠為 true。使用 Bun.Transpiler 在不打包的情況下轉譯。
charsetn/a不支援

chunkNames

naming.chunk

使用與 esbuild 相同的範本語法,但必須明確包含 [ext]

Bun.build({
  entrypoints: ["./index.tsx"],
  naming: {
    chunk: "[name].[ext]",
  },
});
colorn/aBun 在建置結果的 logs 屬性中回傳記錄。
conditionsn/a不支援。匯出條件優先順序由 target 決定。
definedefine
dropn/a不支援

entryNames

namingnaming.entry

Bun 支援一個 naming 鍵,它可以是字串或物件。使用與 esbuild 相同的範本語法,但必須明確包含 [ext]

Bun.build({
  entrypoints: ["./index.tsx"],
  // when string, this is equivalent to entryNames
  naming: "[name].[ext]",

  // granular naming options
  naming: {
    entry: "[name].[ext]",
    asset: "[name].[ext]",
    chunk: "[name].[ext]",
  },
});
entryPointsentrypoints大小寫差異
externalexternal沒有差異
footern/a不支援
formatformat目前僅支援 "esm"。已規劃支援 "cjs""iife"
globalNamen/a不支援
ignoreAnnotationsn/a不支援
injectn/a不支援
jsxjsxJS API 中不支援,請在 tsconfig.json 中設定
jsxDevjsxDevJS API 中不支援,請在 tsconfig.json 中設定
jsxFactoryjsxFactoryJS API 中不支援,請在 tsconfig.json 中設定
jsxFragmentjsxFragmentJS API 中不支援,請在 tsconfig.json 中設定
jsxImportSourcejsxImportSourceJS API 中不支援,請在 tsconfig.json 中設定
jsxSideEffectsjsxSideEffectsJS API 中不支援,請在 tsconfig.json 中設定
keepNamesn/a不支援
legalCommentsn/a不支援
loaderloaderBun 支援與 esbuild 不同的內建載入器組;請參閱 Bundler > Loaders 以取得完整參考。esbuild 載入器 dataurlbinarybase64copyempty 尚未實作。
logLeveln/a不支援
logLimitn/a不支援
logOverriden/a不支援
mainFieldsn/a不支援
mangleCachen/a不支援
manglePropsn/a不支援
mangleQuotedn/a不支援
metafilen/a不支援

minify

minify

在 Bun 中,minify 可以是布林值或物件。

Bun.build({
  entrypoints: ['./index.tsx'],
  // enable all minification
  minify: true

  // granular options
  minify: {
    identifiers: true,
    syntax: true,
    whitespace: true
  }
})
minifyIdentifiersminify.identifiers請參閱 minify
minifySyntaxminify.syntax請參閱 minify
minifyWhitespaceminify.whitespace請參閱 minify
nodePathsn/a不支援
outExtensionn/a不支援
outbaseroot名稱不同
outdiroutdir沒有差異
outfileoutfile沒有差異
packagesn/a不支援,請使用 external
platformtarget支援 "bun""node""browser"(預設)。不支援 "neutral"
pluginspluginsBun 的外掛 API 是 esbuild 的子集。有些 esbuild 外掛可以使用在 Bun 中。
preserveSymlinksn/a不支援
publicPathpublicPath沒有差異
puren/a不支援
reservePropsn/a不支援
resolveExtensionsn/a不支援
sourceRootn/a不支援
sourcemapsourcemap支援 "inline""external""none"
sourcesContentn/a不支援
splittingsplitting沒有差異
stdinn/a不支援
supportedn/a不支援
targetn/a不支援語法降級
treeShakingn/a永遠為 true
tsconfign/a不支援
writen/a如果設定了 outdir/outfile,則設定為 true,否則為 false

外掛 API

Bun 的外掛 API 設計為與 esbuild 相容。Bun 不支援 esbuild 的所有外掛 API,但已實作核心功能。許多第三方 esbuild 外掛可以使用在 Bun 中。

長期而言,我們目標是與 esbuild 的 API 達到功能相等,因此如果有些功能無法使用,請提交問題以協助我們優先處理。

Bun 和 esbuild 中的外掛是使用 builder 物件定義的。

import type { BunPlugin } from "bun";

const myPlugin: BunPlugin = {
  name: "my-plugin",
  setup(builder) {
    // define plugin
  },
};

builder 物件提供了一些方法,用於連接到打包程式的部分。Bun 實作了 onResolveonLoad;尚未實作 esbuild 的 onStartonEndonDispose 鉤子,以及 resolve 工具程式。initialOptions 已部分實作,為唯讀且僅包含 esbuild 選項的子集;請改用 config(與 Bun 的 BuildConfig 格式相同)。

import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
  name: "my-plugin",
  setup(builder) {
    builder.onResolve(
      {
        /* onResolve.options */
      },
      args => {
        return {
          /* onResolve.results */
        };
      },
    );
    builder.onLoad(
      {
        /* onLoad.options */
      },
      args => {
        return {
          /* onLoad.results */
        };
      },
    );
  },
};

onResolve

選項

🟢篩選器
🟢命名空間

參數

🟢路徑
🟢匯入程式
🔴命名空間
🔴解析目錄
🔴類型
🔴外掛程式資料

結果

🟢命名空間
🟢路徑
🔴錯誤
🔴external
🔴外掛程式資料
🔴外掛程式名稱
🔴副作用
🔴字尾
🔴警告
🔴監控目錄
🔴監控檔案

onLoad

選項

🟢篩選器
🟢命名空間

參數

🟢路徑
🔴命名空間
🔴字尾
🔴外掛程式資料

結果

🟢內容
🟢loader
🔴錯誤
🔴外掛程式資料
🔴外掛程式名稱
🔴解析目錄
🔴警告
🔴監控目錄
🔴監控檔案