Skip to main content
--define 标志声明可在静态分析中确定的常量和全局变量。它会将 JavaScript 或 TypeScript 文件中的标识符或属性的所有使用替换为常量值,并且在运行时和 bun build 中均可工作。这类似于 C/C++ 中的 #define,但适用于 JavaScript。
terminal

Bun 使用这些静态已知的值进行死代码消除和其他优化。

在代码到达 JavaScript 引擎之前,Bun 会将 process.env.NODE_ENV 替换为 "production"

Bun 的优化转译器还会进行基本的常量折叠。 由于 "production" === "production" 始终为 true,Bun 会将整个表达式替换为 true 并丢弃不可达的 else 分支。

要进一步将外围的 if 框架折叠为以下输出,请传入 --minify-syntax(也由 --minify 启用):
terminal

支持哪些类型的值?

值可以是字符串、标识符、属性或 JSON。

替换全局标识符

将所有 window 的使用替换为 undefined
这对于服务端渲染(SSR)很有用,或者确保代码不依赖于 window 对象。
该值也可以是另一个标识符。例如,将所有 global 的使用替换为 globalThis
global 是 Node.js 中的全局对象,但在 Web 浏览器中不是,因此此替换可修复假定 global 可用的代码。

用 JSON 替换值

--define 还可以用 JSON 对象和数组替换值。 要将所有 AWS 的使用替换为 JSON 对象 {"ACCESS_KEY":"abc","SECRET_KEY":"def"}
Bun 将这些转换为等效的 JavaScript 代码。 转换前:
转换后:

用其他属性替换值

你也可以向 --define 标志传递属性。 例如,将所有 console.write 的使用替换为 console.log
这会将以下输入:
转换为以下输出:

这与设置变量有何不同?

你也可以在代码中将 process.env.NODE_ENV 设置为 "production",但这无助于死代码消除。在 JavaScript 中,属性访问可能有副作用。Getter 和 setter 可以是函数,甚至可以是动态定义的(由于原型链和 Proxy)。即使你将 process.env.NODE_ENV 设置为 "production",静态分析工具也无法保证它在下一行仍然是 "production"

这与查找替换或字符串替换有何不同?

--define 标志操作的是 AST(抽象语法树),而不是文本。替换在转译期间发生,因此它参与诸如死代码消除之类的优化。 字符串替换工具往往存在转义问题,并可能替换代码中不打算被替换的部分。