--define フラグを使用すると、静的に分析可能な定数とグローバル変数を宣言できます。これにより、JavaScript または TypeScript ファイル内の識別子またはプロパティのすべての使用を定数値に置換します。この機能はランタイムと bun build の両方でサポートされています。これは JavaScript 用であることを除いて、C/C++ の #define にある程度似ています。
bun --define process.env.NODE_ENV="'production'" src/index.ts # ランタイム
bun build --define process.env.NODE_ENV="'production'" src/index.ts # ビルドこれらの静的に既知の値は、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.tsglobal は 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 --define console.write=console.log src/index.tsこれにより、次の入力が変換されます。
console.write("Hello, world!");次の出力に変換されます。
console.log("Hello, world!");変数を設定するのとどう違うのですか?
コード内で process.env.NODE_ENV を "production" に設定することもできますが、それはデッドコード削除には役立ちません。JavaScript では、プロパティアクセスには副作用がある可能性があります。ゲッターとセッターは関数であり、動的に定義されることさえあります(プロトタイプチェーンと Proxy により)。process.env.NODE_ENV を "production" に設定しても、次の行で process.env.NODE_ENV が "production" であると静的解析ツールが仮定するのは安全ではありません。
検索と置換や文字列置換とどう違うのですか?
--define フラグはテキストレベルではなく AST(抽象構文木)レベルで動作します。これはトランスパイルプロセス中に発生するため、デッドコード削除などの最適化に使用できます。
文字列置換ツールは、エスケープの問題が発生したり、意図しないコード部分を置換したりする傾向があります。