为什么webpack的tree-shaking会移除看似存在副作用的代码?
问题原因解答
该现象是生产模式下Terser压缩工具的死代码消除(DCE)能力导致的,和webpack的tree shaking、sideEffects配置无关,具体逻辑如下:
- 首先要区分两个不同的优化逻辑:
- webpack原生的tree shaking是基于ES模块导入导出关系的顶层优化,核心作用是剔除模块中未被其他模块导入使用的导出成员,
sideEffects配置仅作用于这一层优化,用来告诉webpack哪些模块即使导出没有被使用也不能整体删除。 - webpack
mode: production默认启用的TerserPlugin会做语义级别的死代码消除,它会分析代码的实际执行效果,只要一段代码执行后不会对全局上下文产生任何可观测的副作用,就会被判定为死代码直接删除,不受webpack层面的tree shaking规则约束。
- webpack原生的tree shaking是基于ES模块导入导出关系的顶层优化,核心作用是剔除模块中未被其他模块导入使用的导出成员,
- 对应你的代码片段:
const bar = () => 11111仅返回固定常量,没有修改全局变量、调用console/DOM等有副作用的API,本身无任何副作用foo函数仅调用bar并返回结果,自身也没有产生副作用的逻辑- 最终的
foo()调用返回值没有被任何变量接收或后续处理,整个调用链执行完不会对程序运行产生任何可观测的影响
所以Terser在压缩阶段直接把bar、foo的定义和调用全部判定为死代码删除,你自然在打包产物里找不到相关代码。
验证方法:你可以在
bar函数内部添加一行console.log('test'),此时这段代码就有了可观测的副作用,Terser不会再删除,打包后就能看到相关代码。
内容的提问来源于stack exchange,提问作者Chor
相关产品推荐
相关产品推荐

