Bun

Bun.build

Bun 的快速原生打包器現在處於測試階段。它可以使用 bun build CLI 命令或 Bun.build() JavaScript API。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './build',
});
CLI
bun build ./index.tsx --outdir ./build

速度很快。以下數字代表 esbuild 在 three.js 基準 上的效能。

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

為何要打包?

打包器是 JavaScript 生態系統中的重要基礎架構。以下是打包如此重要的簡要說明

  • 減少 HTTP 要求。node_modules 中的單一套件可能包含數百個檔案,而大型應用程式可能會有數十個此類依賴項。使用個別 HTTP 要求載入這些檔案很快就會變得難以處理,因此打包器用於將我們的應用程式原始碼轉換成較少數量的自給自足「套件」,這些套件可以使用單一要求載入。
  • 程式碼轉換。現代應用程式通常使用 TypeScript、JSX 和 CSS 模組等語言或工具建置,所有這些都必須轉換成純 JavaScript 和 CSS,才能讓瀏覽器使用。打包器是設定這些轉換的自然所在。
  • 架構功能。架構仰賴打包器外掛程式和程式碼轉換來實作常見模式,例如檔案系統路由、客戶端伺服器程式碼共置(想想 getServerSideProps 或 Remix 載入器)和伺服器元件。

讓我們深入了解打包器 API。

請注意,Bun 打包器並非用於取代 tsc 進行類型檢查或產生類型宣告。

基本範例

讓我們建置第一個套件。您有以下兩個檔案,它們實作一個簡單的客戶端渲染 React 應用程式。

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

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

在此,index.tsx 是我們應用程式的「進入點」。通常,這會是一個執行某些副作用的指令碼,例如啟動伺服器或(在本例中)初始化 React 根。由於我們使用 TypeScript 和 JSX,因此需要在將程式碼傳送至瀏覽器之前先打包我們的程式碼。

建立我們的套件

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
})
CLI
bun build ./index.tsx --outdir ./out

對於 entrypoints 中指定的每個檔案,Bun 會產生一個新的套件。此套件會寫入到磁碟中的 ./out 目錄(從目前的作業目錄解析)。執行建置後,檔案系統會如下所示

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

out/index.js 的內容會類似這樣

out/index.js
// ...
// ~20k lines of code
// including the contents of `react-dom/client` and all its dependencies
// this is where the $jsxDEV and $createRoot functions are defined


// 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));

教學:在瀏覽器中執行此檔案

監控模式

與執行時期和測試執行器一樣,套件管理程式本機支援監控模式。

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

內容類型

與 Bun 執行時期一樣,套件管理程式預設支援多種檔案類型。下表細分了套件管理程式的標準「載入器」組。有關完整文件,請參閱 套件管理程式 > 檔案類型

副檔名詳細資料
.js .jsx, .cjs .mjs .mts .cts .ts .tsx使用 Bun 內建的轉譯器來解析檔案,並將 TypeScript/JSX 語法轉譯為純粹的 JavaScript。套件管理程式執行一組預設轉換,包括死碼消除和樹狀搖晃。目前,Bun 沒有嘗試向下轉換語法;如果您使用最近的 ECMAScript 語法,這將反映在套件程式碼中。

.json

JSON 檔案會被解析並內嵌到套件中,作為 JavaScript 物件。

import pkg from "./package.json";
pkg.name; // => "my-package"

.toml

TOML 檔案會被解析並內嵌到套件中,作為 JavaScript 物件。

import config from "./bunfig.toml";
config.logLevel; // => "debug"

.txt

文字檔的內容會讀取並以字串形式內嵌到套件中。

import contents from "./file.txt";
console.log(contents); // => "Hello, world!"
.node .wasmBun 執行階段支援這些檔案,但在套件處理期間,它們會被視為 資產

資產

如果套件處理器遇到無法辨識的副檔名匯入,它會將匯入的檔案視為外部檔案。所引用的檔案會原樣複製到 outdir,而匯入會解析為檔案的路徑

輸入
輸出
輸入
// bundle entrypoint
import logo from "./logo.svg";
console.log(logo);
輸出
// bundled output
var logo = "./logo-ab237dfe.svg";
console.log(logo);

檔案載入器的確切行為也會受到 命名publicPath 的影響。

請參閱 套件處理器 > 載入器 頁面,以取得檔案載入器的更完整文件。

外掛程式

此表格中所述的行為可以用 外掛程式 覆寫或擴充。請參閱 套件處理器 > 載入器 頁面,以取得完整的說明文件。

API

entrypoints

必要。一個路徑陣列,對應到我們應用程式的進入點。會為每個進入點產生一個套件。

JavaScript
CLI
JavaScript
const result = await Bun.build({
  entrypoints: ["./index.ts"],
});
// => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
CLI
bun build --entrypoints ./index.ts
# the bundle will be printed to stdout
# <bundled code>

outdir

輸出檔案會寫入的目錄。

JavaScript
CLI
JavaScript
const result = await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out'
});
// => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }
CLI
bun build --entrypoints ./index.ts --outdir ./out
# a summary of bundled files will be printed to stdout

如果 outdir 未傳遞到 JavaScript API,套件處理的程式碼不會寫入磁碟。套件處理的檔案會以 BuildArtifact 物件陣列的形式傳回。這些物件是具有額外屬性的 Blob;請參閱 輸出 以取得完整的說明文件。

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

for (const res of result.outputs) {
  // Can be consumed as blobs
  await res.text();

  // Bun will set Content-Type and Etag headers
  new Response(res);

  // Can be written manually, but you should use `outdir` in this case.
  Bun.write(path.join("out", res.path), res);
}

當設定 outdir 時, BuildArtifact 上的 path 屬性將會是寫入的絕對路徑。

target

套件預計執行的環境。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './out',
  target: 'browser', // default
})
CLI
bun build --entrypoints ./index.ts --outdir ./out --target browser

Bun 會根據目標套用不同的模組解析規則和最佳化。

browser預設。用於產生預計由瀏覽器執行的套件。解析匯入時,優先考慮 "browser" 匯出條件。匯入任何內建模組,例如 node:eventsnode:path 都會運作,但呼叫某些函式,例如 fs.readFile 則無法運作。

bun

用於產生預計由 Bun 執行時期執行的套件。在許多情況下,不需要套件伺服器端程式碼;你可以直接執行原始碼而不用修改。然而,套件伺服器端程式碼可以減少啟動時間並提升執行效能。

所有以 target: "bun" 產生的套件都標記有特殊 // @bun 註解,這表示 Bun 執行時期在執行前不需要重新編譯檔案。

如果任何進入點包含 Bun shebang (#!/usr/bin/env bun),套件產生器會預設為 target: "bun" 而不是 "browser"

node用於產生預計由 Node.js 執行的套件。解析匯入時,優先考慮 "node" 匯出條件,並輸出 .mjs。未來,這將會自動填充 Bun 全域變數和其他內建 bun:* 模組,儘管這尚未實作。

format

指定在產生的套件中使用的模組格式。

目前套件產生器只支援一種模組格式:"esm"。計畫支援 "cjs""iife"

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

splitting

是否啟用程式碼拆分。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  splitting: false, // default
})
CLI
bun build ./index.tsx --outdir ./out --splitting

true 時,bundler 將啟用程式碼拆分。當多個進入點同時匯入同一個檔案、模組或檔案/模組組時,通常會將共用程式碼拆分到一個獨立的 bundle。這個共用 bundle 稱為區塊。考慮以下檔案

entry-a.ts
entry-b.ts
shared.ts
entry-a.ts
import { shared } from './shared.ts';
entry-b.ts
import { shared } from './shared.ts';
shared.ts
export const shared = 'shared';

若要使用啟用程式碼拆分的 entry-a.tsentry-b.ts

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

執行此建置會產生以下檔案

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

產生的 chunk-2fce6291bf86559d.js 檔案包含共用程式碼。為了避免衝突,檔案名稱預設會自動包含內容雜湊。這可以用 naming 自訂。

plugins

在 bundling 期間使用的外掛清單。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  plugins: [/* ... */],
})
CLI
n/a

Bun 為 Bun 的執行時間和 bundler 實作一個通用外掛系統。請參閱 外掛文件 以取得完整文件。

sourcemap

指定要產生的 sourcemap 類型。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  sourcemap: "external", // default "none"
})
CLI
bun build ./index.tsx --outdir ./out --sourcemap=external
"none"預設。不會產生 sourcemap。

"inline"

會產生 sourcemap,並附加到產生的 bundle 的結尾,作為 base64 payload。

// <bundled code here>

//# sourceMappingURL=data:application/json;base64,<encoded sourcemap here>
"external"會在每個 *.js bundle 旁邊建立一個獨立的 *.js.map 檔案。

產生的 bundle 包含一個 偵錯 ID,可用於將 bundle 與其對應的 sourcemap 關聯起來。這個 debugId 會新增為檔案底部的註解。

// <generated bundle code>

//# debugId=<DEBUG ID>

關聯的 *.js.map sourcemap 會是一個 JSON 檔案,包含一個等效的 debugId 屬性。

minify

是否啟用縮小化。預設為 false

當目標為 bun 時,預設會縮小化識別碼。

若要啟用所有縮小化選項

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  minify: true, // default false
})
CLI
bun build ./index.tsx --outdir ./out --minify

若要詳細啟用某些縮小化

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

external

一個要考慮為外部的匯入路徑清單。預設為 []

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  external: ["lodash", "react"], // default: []
})
CLI
bun build ./index.tsx --outdir ./out --external lodash --external react

外部匯入是不會包含在最終套件中的。相反地,import 陳述會保持原樣,在執行階段解析。

例如,考慮下列入口點檔案

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

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

通常,套件化 index.tsx 會產生一個套件,其中包含 "zod" 套件的完整原始碼。如果我們希望保持 import 陳述原樣,我們可以將其標記為外部

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

產生的套件會類似這樣

out/index.js
import {z} from "zod";

// ...
// the contents of the "lodash" package
// including the `_.upperCase` function

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

若要將所有匯入標記為外部,請使用萬用字元 *

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

naming

自訂產生的檔案名稱。預設為 ./[dir]/[name].[ext]

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: "[dir]/[name].[ext]", // default
})
CLI
bun build ./index.tsx --outdir ./out --entry-naming [dir]/[name].[ext]

預設情況下,產生的套件名稱會根據關聯入口點的名稱而定。

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

使用多個入口點時,產生的檔案階層會反映入口點的目錄結構。

.
├── 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
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: 'files/[dir]/[name]-[hash].[ext]',
})
CLI
bun build ./index.tsx --outdir ./out --entry-naming [name]-[hash].[ext]

此建置會產生下列檔案結構

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

當為 naming 欄位提供 string 時,它只會用於對應於入口點的套件。不會影響區塊和複製資產的名稱。使用 JavaScript API,可以為每種類型的產生的檔案指定不同的範本字串。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  naming: {
    // default values
    entry: '[dir]/[name].[ext]',
    chunk: '[name]-[hash].[ext]',
    asset: '[name]-[hash].[ext]',
  },
})
CLI
bun build ./index.tsx --outdir ./out --entry-naming "[dir]/[name].[ext]" --chunk-naming "[name]-[hash].[ext]" --asset-naming "[name]-[hash].[ext]"

root

專案的根目錄。

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

如果未指定,會計算為所有入口點檔案的第一個共同祖先。考慮下列檔案結構

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

我們可以在 pages 目錄中建置兩個入口點

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

這會產生類似這樣的檔案結構

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

由於 pages 目錄是入口點檔案的第一個共同祖先,因此它被視為專案根目錄。這表示產生的套件會存在於 out 目錄的最上層;沒有 out/pages 目錄。

可以透過指定 root 選項來覆寫此行為

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

透過將 . 指定為 root,產生的檔案結構會類似這樣

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

publicPath

要附加到套件程式碼中任何匯入路徑的前置詞。

在許多情況下,產生的套件不會包含任何 import 陳述式。畢竟,套件的目的就是將所有程式碼結合到單一檔案中。不過,有許多情況下產生的套件會包含 import 陳述式。

  • 資源匯入 — 在匯入未識別的檔案類型(例如 *.svg)時,套件組建器會轉向 file 載入器,它會將檔案原樣複製到 outdir 中。匯入會轉換成變數
  • 外部模組 — 檔案和模組可以標示為 external,這樣就不會包含在套件中。反之,import 陳述式會保留在最後的套件中。
  • 區塊化。當 splitting 已啟用時,套件組建器可能會產生代表在多個入口點中共用的程式碼的個別「區塊」檔案。

在任何這些情況下,最後的套件都可能會包含其他檔案的路徑。預設情況下,這些匯入是相對的。以下是簡單資源匯入的範例

輸入
輸出
輸入
import logo from './logo.svg';
console.log(logo);
輸出
// logo.svg is copied into <outdir>
// and hash is added to the filename to prevent collisions
var logo = './logo-a7305bdef.svg';
console.log(logo);

設定 publicPath 會使用指定的值為所有檔案路徑加上前置詞。

JavaScript
CLI
JavaScript
await Bun.build({
  entrypoints: ['./index.tsx'],
  outdir: './out',
  publicPath: 'https://cdn.example.com/', // default is undefined
})
CLI
bun build ./index.tsx --outdir ./out --public-path https://cdn.example.com/

輸出檔案現在看起來像這樣。

輸出
var logo = './logo-a7305bdef.svg';
var logo = 'https://cdn.example.com/logo-a7305bdef.svg';

define

在建置時要替換的全球識別碼對應表。此物件的鍵是識別碼名稱,而值是會內嵌的 JSON 字串。

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

loader

檔案副檔名對應到內建載入器名稱的對應表。這可以用來快速自訂如何載入特定檔案。

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

輸出

Bun.build 函式會傳回一個 Promise<BuildOutput>,定義如下

interface BuildOutput {
  outputs: BuildArtifact[];
  success: boolean;
  logs: Array<object>; // see docs for details
}

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

outputs 陣列包含建置產生的所有檔案。每個成品都實作 Blob 介面。

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

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

每個成品也包含下列屬性

kind此檔案的建置輸出類型。建置會產生已綑綁的進入點、程式碼分割「區塊」、原始碼對應表和已複製的資源(例如圖片)。
path檔案在磁碟上的絕對路徑
loader載入器用於詮釋檔案。請參閱 Bundler > Loaders,了解 Bun 如何將檔案副檔名對應到適當的內建載入器。
hash檔案內容的雜湊。永遠會定義為資源。
sourcemap對應到此檔案的原始碼對應表檔案(如果已產生)。只會定義為進入點和區塊。

類似於 BunFileBuildArtifact 物件可以直接傳遞到 new Response()

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

const artifact = build.outputs[0];

// Content-Type header is automatically set
return new Response(artifact);

Bun 執行時間實作 BuildArtifact 物件的特殊漂亮列印,以簡化除錯。

建置指令碼
Shell 輸出
建置指令碼
// build.ts
const build = await Bun.build({/* */});

const artifact = build.outputs[0];
console.log(artifact);
Shell 輸出
bun run build.ts
BuildArtifact (entry-point) {
  path: "./index.js",
  loader: "tsx",
  kind: "entry-point",
  hash: "824a039620219640",
  Blob (114 bytes) {
    type: "text/javascript;charset=utf-8"
  },
  sourcemap: null
}

可執行檔

Bun 支援將 JavaScript/TypeScript 進入點「編譯」成獨立的可執行檔。此可執行檔包含 Bun 二進位檔的副本。

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

請參閱 Bundler > Executables,以取得完整的說明文件。

記錄和錯誤

Bun.build 只有在提供無效選項時才會擲回例外。請讀取 success 屬性,以判斷建置是否成功;logs 屬性會包含其他詳細資料。

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

if (!result.success) {
  console.error("Build failed");
  for (const message of result.logs) {
    // Bun will pretty print the message object
    console.error(message);
  }
}

每則訊息都是 BuildMessageResolveMessage 物件,可用於追蹤建置中發生的問題。

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;
}

如果您想從失敗的建置擲回例外,請考慮將記錄傳遞到 AggregateError。如果未捕捉到,Bun 會漂亮列印包含的訊息。

if (!result.success) {
  throw new AggregateError(result.logs, "Build failed");
}

參考

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

interface BuildOptions {
  entrypoints: string[]; // required
  outdir?: string; // default: no write (in-memory only)
  format?: "esm"; // later: "cjs" | "iife"
  target?: "browser" | "bun" | "node"; // "browser"
  splitting?: boolean; // true
  plugins?: BunPlugin[]; // [] // See https://bun.dev.org.tw/docs/bundler/plugins
  loader?: { [k in string]: Loader }; // See https://bun.dev.org.tw/docs/bundler/loaders
  manifest?: boolean; // false
  external?: string[]; // []
  sourcemap?: "none" | "inline" | "external"; // "none"
  root?: string; // computed from entrypoints
  naming?:
    | string
    | {
        entry?: string; // '[dir]/[name].[ext]'
        chunk?: string; // '[name]-[hash].[ext]'
        asset?: string; // '[name]-[hash].[ext]'
      };
  publicPath?: string; // e.g. http://mydomain.com/
  minify?:
    | boolean // false
    | {
        identifiers?: boolean;
        whitespace?: boolean;
        syntax?: boolean;
      };
}

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

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

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

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;
}