Skip to content

--define 標志允許你聲明可靜態分析的常量和全局變量。它會替換 JavaScript 或 TypeScript 文件中所有標識符或屬性的使用為常量值。此功能在運行時和 bun build 中都受支持。這類似於 C/C++ 中的 #define,但用於 JavaScript。

sh
bun --define process.env.NODE_ENV="'production'" src/index.ts # 運行時
bun build --define process.env.NODE_ENV="'production'" src/index.ts # 構建

Bun 使用這些靜態已知的值進行死代碼消除和其他優化。

ts
if (process.env.NODE_ENV === "production") {
  console.log("生產模式");
} else {
  console.log("開發模式");
}

在代碼到達 JavaScript 引擎之前,Bun 會將 process.env.NODE_ENV 替換為 "production"

ts
if ("production" === "production") { 
  console.log("生產模式");
} else {
  console.log("開發模式");
}

還不止於此。Bun 的優化轉譯器足夠智能,可以執行一些基本的常量折疊。

由於 "production" === "production" 始終為 true,Bun 會將整個表達式替換為 true 值。

ts
if (true) { 
  console.log("生產模式");
} else {
  console.log("開發模式");
}

最後,Bun 檢測到 else 分支無法到達,並將其消除。

ts
console.log("生產模式");

支持哪些類型的值?

值可以是字符串、標識符、屬性或 JSON。

替換全局標識符

要使 window 的所有用法都變為 undefined,你可以使用以下命令。

sh
bun --define window="undefined" src/index.ts

這在進行服務器端渲染 (SSR) 或當你想確保代碼不依賴於 window 對象時非常有用。

js
if (typeof window !== "undefined") {
  console.log("客戶端代碼");
} else {
  console.log("服務器端代碼");
}

你還可以將值設置為另一個標識符。例如,要使 global 的所有用法都變為 globalThis,你可以使用以下命令。

sh
bun --define global="globalThis" src/index.ts

global 是 Node.js 中的全局對象,但在 Web 瀏覽器中不是。因此,你可以使用它來修復某些假設 global 可用的情況。

使用 JSON 替換值

--define 還可用於使用 JSON 對象和數組替換值。

要將 AWS 的所有用法替換為 JSON 對象 {"ACCESS_KEY":"abc","SECRET_KEY":"def"},你可以使用以下命令。

sh
# JSON
bun --define AWS='{"ACCESS_KEY":"abc","SECRET_KEY":"def"}' src/index.ts

這些將被轉換為等效的 JavaScript 代碼。

從:

ts
console.log(AWS.ACCESS_KEY); // => "abc"

到:

ts
console.log("abc");

使用其他屬性替換值

你還可以將屬性傳遞給 --define 標志。

例如,要將 console.write 的所有用法替換為 console.log,你可以使用以下命令

sh
bun --define console.write=console.log src/index.ts

這會轉換以下輸入:

ts
console.write("你好,世界!");

轉換為以下輸出:

ts
console.log("你好,世界!");

這與設置變量有何不同?

你也可以在代碼中將 process.env.NODE_ENV 設置為 "production",但這對死代碼消除沒有幫助。在 JavaScript 中,屬性訪問可能會產生副作用。getter 和 setter 可以是函數,甚至可以動態定義(由於原型鏈和 Proxy)。即使你將 process.env.NODE_ENV 設置為 "production",在下一行,靜態分析工具假設 process.env.NODE_ENV"production" 也是不安全的。

這與查找替換或字符串替換有何不同?

--define 標志在 AST(抽象語法樹)級別運行,而不是在文本級別運行。它發生在轉譯過程中,這意味著它可用於死代碼消除等優化。

字符串替換工具往往存在轉義問題,並會替換代碼中非預期的部分。

Bun學習網由www.bunjs.com.cn整理維護