執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

使用 --define 實現建置時常量

將 --define 傳遞給 bun build 或 bun build --compile,即可將建置時常量注入應用程式。您可以使用它將建置版本、時間戳或設定標誌等後設資料直接嵌入編譯後的執行檔中。

terminal
bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/index.ts --outfile myapp

為什麼使用建置時常量?

Bun 會將建置時常量直接嵌入編譯後的程式碼中,使其具有以下特點:

  • 零執行環境開銷 – 不需要環境變數查詢或檔案讀取
  • 不可變 – 值在編譯時烘焙進二進位制檔案
  • 可最佳化 – 未使用的分支可以被死程式碼消除
  • 安全 – 無需管理外部相依或設定檔

建置時常量類似於 C/C++ 中的 gcc -D 或 #define,但適用於 JavaScript/TypeScript。


基本用法

使用 bun build

terminal
# 帶建置時常量打包
bun build --define BUILD_VERSION='"1.0.0"' --define NODE_ENV='"production"' src/index.ts --outdir ./dist

使用 bun build --compile

terminal
# 帶建置時常量編譯為執行檔
bun build --compile --define BUILD_VERSION='"1.0.0"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli

JavaScript API

build.ts
await Bun.build({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  define: {
    BUILD_VERSION: '"1.0.0"',
    BUILD_TIME: '"2024-01-15T10:30:00Z"',
    DEBUG: "false",
  },
});

常見用例

版本資訊

將版本和建置後設資料直接嵌入執行檔:

src/version.ts
// 這些常量在建置時被替換
declare const BUILD_VERSION: string;
declare const BUILD_TIME: string;
declare const GIT_COMMIT: string;

export function getVersion() {
  return {
    version: BUILD_VERSION,
    buildTime: BUILD_TIME,
    commit: GIT_COMMIT,
  };
}
Build
bun build --compile \
  --define BUILD_VERSION='"1.2.3"' \
  --define BUILD_TIME='"2024-01-15T10:30:00Z"' \
  --define GIT_COMMIT='"abc123"' \
  src/cli.ts --outfile mycli

功能開關

使用建置時常量啟用或停用功能:

src/app.ts
// Replaced at build time
declare const ENABLE_ANALYTICS: boolean;
declare const ENABLE_DEBUG: boolean;

function trackEvent(event: string) {
  if (ENABLE_ANALYTICS) {
    // 如果 ENABLE_ANALYTICS 為 false,整個程式碼塊將被移除
    console.log("Tracking:", event);
  }
}

if (ENABLE_DEBUG) {
  console.log("除錯模式已啟用");
}
shell
# 生產環境建置 - 啟用分析,關閉除錯
bun build --compile --define ENABLE_ANALYTICS=true --define ENABLE_DEBUG=false src/app.ts --outfile app-prod

# Development build - analytics disabled, debug enabled
bun build --compile --define ENABLE_ANALYTICS=false --define ENABLE_DEBUG=true src/app.ts --outfile app-dev

設定

在建置時替換設定物件:

src/app.ts
declare const CONFIG: {
  apiUrl: string;
  timeout: number;
  retries: number;
};

// CONFIG 在建置時被替換為實際物件
const response = await fetch(CONFIG.apiUrl, {
  timeout: CONFIG.timeout,
});
shell
bun build --compile --define 'CONFIG={"apiUrl":"https://api.example.com","timeout":5000,"retries":3}' src/app.ts --outfile app

高階用法

不同環境的建置

為不同環境建立不同的執行檔:

JSON
{
  "scripts": {
    "build:dev": "bun build --compile --define NODE_ENV='\"development\"' --define API_URL='\"http://localhost:3000\"' src/app.ts --outfile app-dev",
    "build:staging": "bun build --compile --define NODE_ENV='\"staging\"' --define API_URL='\"https://staging.example.com\"' src/app.ts --outfile app-staging",
    "build:prod": "bun build --compile --define NODE_ENV='\"production\"' --define API_URL='\"https://api.example.com\"' src/app.ts --outfile app-prod"
  }
}

使用 Shell 命令生成動態值

通過 Shell 命令生成建置時常量:

shell
# 使用 git 獲取當前提交號和時間戳
bun build --compile \
  --define BUILD_VERSION="\"$(git describe --tags --always)\"" \
  --define BUILD_TIME="\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"" \
  --define GIT_COMMIT="\"$(git rev-parse HEAD)\"" \
  src/cli.ts --outfile mycli

建置自動化指令碼

建立一個注入建置後設資料的建置指令碼:

TypeScript
// build.ts
import { $ } from "bun";

const version = await $`git describe --tags --always`.text();
const buildTime = new Date().toISOString();
const gitCommit = await $`git rev-parse HEAD`.text();

await Bun.build({
  entrypoints: ["./src/cli.ts"],
  outdir: "./dist",
  define: {
    BUILD_VERSION: JSON.stringify(version.trim()),
    BUILD_TIME: JSON.stringify(buildTime),
    GIT_COMMIT: JSON.stringify(gitCommit.trim()),
  },
});

console.log(`建置版本為 ${version.trim()}`);

重要注意事項

值的格式

值可以是 JSON、識別符號或屬性路徑,例如 globalThis 或 console.log。Bun 會解析每個值,並將其作為 JavaScript 表示式內聯:

shell
# ✅ 字串必須用 JSON 引號包裹
--define VERSION='"1.0.0"'

# ✅ 數字是 JSON 字面量
--define PORT=3000

# ✅ 布林值是 JSON 字面量
--define DEBUG=true

# ✅ 物件和陣列(使用單引號包裹 JSON)
--define 'CONFIG={"host":"localhost","port":3000}'

# ✅ 陣列也可以
--define 'FEATURES=["auth","billing","analytics"]'

# ❌ 以下寫法無效 - 字串缺少引號
--define VERSION=1.0.0

屬性鍵名

鍵也可以是屬性訪問模式,而不僅限於普通識別符號:

shell
# ✅ 替換 process.env.NODE_ENV 為 "production"
--define 'process.env.NODE_ENV="production"'

# ✅ 替換 process.env.API_KEY 為實際的金鑰
--define 'process.env.API_KEY="abc123"'

# ✅ 替換巢狀屬性
--define 'window.myApp.version="1.0.0"'

使用此功能可以在建置時內聯環境變數:

TypeScript
// 編譯前
if (process.env.NODE_ENV === "production") {
  console.log("生產模式");
}

// 使用 --define 'process.env.NODE_ENV="production"' 編譯後
if ("production" === "production") {
  console.log("生產模式");
}

// 最佳化後
console.log("生產模式");

TypeScript 宣告

對於 TypeScript 專案,宣告常量以避免型別錯誤:

TypeScript
// types/build-constants.d.ts
declare const BUILD_VERSION: string;
declare const BUILD_TIME: string;
declare const NODE_ENV: "development" | "staging" | "production";
declare const DEBUG: boolean;

跨平臺相容性

針對多個平臺建置時,常量的用法相同:

shell
# Linux
bun build --compile --target=bun-linux-x64 --define PLATFORM='"linux"' src/app.ts --outfile app-linux

# macOS
bun build --compile --target=bun-darwin-x64 --define PLATFORM='"darwin"' src/app.ts --outfile app-macos

# Windows
bun build --compile --target=bun-windows-x64 --define PLATFORM='"windows"' src/app.ts --outfile app-windows.exe

相關連結