--define 標誌允許你宣告靜態可分析的常量和全域性變數。它會將 JavaScript 或 TypeScript 檔案中識別符號或屬性的所有用法替換為一個常量值。此功能在執行時和 `bun build` 中都支援。這有點類似於 C/C++ 中的 `#define`,但用於 JavaScript。
bun --define process.env.NODE_ENV="'production'" src/index.ts # Runtimebun build --define process.env.NODE_ENV="'production'" src/index.ts # Build這些靜態已知值被 Bun 用於死程式碼消除和其他最佳化。
if (process.env.NODE_ENV === "production") {
console.log("Production mode");
} else {
console.log("Development mode");
}
在程式碼到達 JavaScript 引擎之前,Bun 會將 `process.env.NODE_ENV` 替換為 `"production"`。
if ("production" === "production") {
console.log("Production mode");
} else {
console.log("Development mode");
}但這還不是全部。Bun 的最佳化轉譯器足夠智慧,可以執行一些基本的常量摺疊。
由於 `"production" === "production"` 始終為 `true`,Bun 會將整個表示式替換為 `true` 值。
if (true) {
console.log("Production mode");
} else {
console.log("Development mode");
}最後,Bun 檢測到 `else` 分支是不可達的,並將其刪除。
console.log("Production mode");
支援哪些型別的值?
值可以是字串、識別符號、屬性或 JSON。
替換全域性識別符號
要將 `window` 的所有用法替換為 `undefined`,可以使用以下命令。
bun --define window="undefined" src/index.ts
這在伺服器端渲染 (SSR) 時很有用,或者當你想確保程式碼不依賴於 `window` 物件時。
if (typeof window !== "undefined") {
console.log("Client-side code");
} else {
console.log("Server-side code");
}
你也可以將值設定為另一個識別符號。例如,要將 `global` 的所有用法設定為 `globalThis`,可以使用以下命令。
bun --define global="globalThis" src/index.ts
`global` 是 Node.js 中的一個全域性物件,但在 Web 瀏覽器中不是。因此,你可以使用此功能來修復一些程式碼假定 `global` 可用的情況。
用 JSON 替換值
--define 也可用於用 JSON 物件和陣列替換值。
要將 `AWS` 的所有用法替換為 JSON 物件 `{"ACCESS_KEY":"abc","SECRET_KEY":"def"}`,可以使用以下命令。
# JSON
bun --define AWS='{"ACCESS_KEY":"abc","SECRET_KEY":"def"}' src/index.ts
這些將被轉換為等效的 JavaScript 程式碼。
從
console.log(AWS.ACCESS_KEY); // => "abc"
到
console.log("abc");
用其他屬性替換值
你也可以將屬性傳遞給 `--define` 標誌。
例如,要將 `console.write` 的所有用法替換為 `console.log`,可以使用以下命令(需要 Bun v1.1.5 或更高版本)
bun --define console.write=console.log src/index.ts
這會將以下輸入轉換為
console.write("Hello, world!");
轉換為以下輸出
console.log("Hello, world!");
這與設定變數有什麼不同?
你也可以在程式碼中將 `process.env.NODE_ENV` 設定為 `"production"`,但這無助於死程式碼消除。在 JavaScript 中,屬性訪問可能具有副作用。Getter 和 Setter 可以是函式,甚至可以動態定義(由於原型鏈和 Proxy)。即使你將 `process.env.NODE_ENV` 設定為 `"production"`,在下一行,靜態分析工具也不能安全地假定 `process.env.NODE_ENV` 是 `"production"`。
這與查詢和替換或字串替換有什麼不同?
--define 標誌在 AST(抽象語法樹)級別執行,而不是在文字級別。它發生在轉譯過程中,這意味著它可以用於死程式碼消除等最佳化。
字串替換工具往往存在轉義問題,並會替換程式碼中不相關的部分。