--define 标志允许你声明静态可分析的常量和全局变量。它会将 JavaScript 或 TypeScript 文件中所有对某个标识符或属性的使用替换为一个常量值。此功能在运行时和 bun build 中均受到支持。这有点类似于 C/C++ 中的 #define,只是针对 JavaScript 实现的。
terminal
Bun 使用这些静态已知的值进行死代码消除和其他优化。
在代码到达 JavaScript 引擎之前,Bun 会将
process.env.NODE_ENV 替换为 "production"。
这还不是终点。Bun 的优化转译器足够智能,可以进行一些基本的常量折叠。 由于
"production" === "production" 恒为 true,Bun 将整个表达式替换为 true。
最后,Bun 检测到
else 分支不可达,并将其删除。
支持哪些类型的值?
值可以是字符串、标识符、属性或 JSON。替换全局标识符
如果想让所有对window 的使用均为 undefined,可以使用以下命令。
window 对象时。
global 的使用替换成 globalThis,可以使用以下命令。
global 是 Node.js 中的全局对象,但在浏览器中不是。因此,你可以用这个方法修正代码中假设 global 存在的情况。
使用 JSON 替换值
--define 也可以用来替换 JSON 对象和数组。
要将所有 AWS 替换为 JSON 对象 {"ACCESS_KEY":"abc","SECRET_KEY":"def"},可以使用以下命令。
使用其他属性替换值
你也可以传递属性给--define 标志。
例如,要将所有 console.write 替换成 console.log,可以使用以下命令:
这和设置变量有什么不同?
你也可以在代码中将process.env.NODE_ENV 设置为 "production",但这不会有助于死代码消除。在 JavaScript 中,属性访问可能会有副作用。getter 和 setter 可能是函数,甚至是动态定义的(基于原型链和 Proxy)。即便你将 process.env.NODE_ENV 设置为 "production",静态分析工具也不能在下一行假设 process.env.NODE_ENV 就是 "production"。
这和查找替换或字符串替换有什么不同?
--define 标志是在 AST(抽象语法树)级别进行操作,而不是文本级别。它发生在转译过程中,意味着它可以用于诸如死代码消除之类的优化。
字符串替换工具往往有转义问题,并且可能替换到代码中不应替换的部分。