为什么Webpack配置了Tree Shaking后,某些未引用的代码依然被打包进去?
我在项目里配置了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版本也没解决,是不是还有其他配置遗漏?或者导出方式有问题?
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 是不会生效的,别踩这个坑。