为什么Webpack配置了Tree Shaking后,某些未引用的代码依然被打包进去?

庆芳 Dev 阅读 52

我在项目里配置了Webpack的Tree Shaking,但发现未使用的模块还是被打包了。比如这个组件里只用了utils.js的add函数:


// component.jsx
import { add, multiply } from './utils';

function calc() {
  return add(2,3);
}
export default calc;

打包后bundle里依然能看到multiply的代码。检查webpack.config.js已经设置了:

optimization: { usedExports: true }

尝试过升级Webpack到5.x版本也没解决,是不是还有其他配置遗漏?或者导出方式有问题?

我来解答 赞 14 收藏
二维码
手机扫码查看
1 条解答
上官殿薇
这个问题其实挺常见的,Tree Shaking并不是简单地靠 optimization: { usedExports: true } 就能完全生效的。有几个关键点需要注意。

首先,你的 utils.js 文件必须使用 ES Module 的导出方式,也就是 export 语法,而不是 CommonJS 的 module.exports。Webpack 的 Tree Shaking 只对静态分析友好的 ES Module 生效。如果 utils.js 里用了 module.exports 或者混用了 require,那 Tree Shaking 就会失效。

其次,确保 Babel 配置没有把 ES Module 转换成 CommonJS。如果你用的是 Babel,检查一下 babel.config.js 或者 .babelrc,确认没有开启 "modules": "commonjs" 这个选项。如果有,改成 "modules": false,让 Webpack 自己处理模块依赖。

还有就是,你的代码里虽然只用了 add 函数,但 multiply 的代码依然可能被标记为“副作用”。Webpack 默认会认为所有文件都有副作用,除非你明确告诉它哪些文件可以安全移除。可以在 package.json 里加一个字段 sideEffects: false,这样就告诉 Webpack 这个模块是纯函数模块,没有副作用,未引用的部分可以放心移除。

另外,如果你确实有一些文件是有副作用的,比如样式文件或者 polyfill,记得在 sideEffects 字段里显式声明这些文件路径,例如 sideEffects: ["*.css", "*.scss"]。不然可能会误删一些必要的代码。

最后一个小细节,检查一下 TerserPlugin 是否正常工作。Tree Shaking 只是标记了哪些代码是未引用的,真正删除这些代码还得靠 Terser 压缩工具。如果压缩没开,那些标记为未引用的代码还是会被打包进去。

总结一下,按这个顺序检查:确保使用 ES Module、调整 Babel 配置、设置 sideEffects、确认 Terser 正常工作。一般来说按照这些步骤,Tree Shaking 应该就能正常生效了。

对了,记得测试的时候用生产环境模式跑一遍,开发模式下 Tree Shaking 是不会生效的,别踩这个坑。
点赞 3
2026-02-14 09:04