当 "sideeffects": false 写在项目根目录的 package.json 中,表示本项目所有模块均为纯 es 模块,导入时无任何副作用(如改全局变量、操作 dom 等),打包工具可安全剔除未被引用的导出;但需确保代码真实无副作用,否则会导致功能异常,并配合 production 模式、es 模块配置及正确白名单(如 "*.css")才能生效。

当 "sideEffects": false 写在项目根目录的 package.json 中,就等于向 Webpack、Vite 等现代打包工具明确声明:**本项目所有模块都是“纯”的 ES 模块,导入它们不会触发任何外部影响(比如改全局变量、操作 DOM、发起请求、注册插件等)**。工具据此推断——只要某个模块的导出没被任何地方 import 过,整个模块文件就可以安全剔除。
它生效的前提是“纯模块”真实存在
这个配置不是魔法开关,而是你对代码行为的诚实承诺。如果实际有副作用却标了 false,打包后功能可能直接异常。所以需确保:
- 所有源码使用标准 ES6
import/export,不混用require或module.exports - 没有顶层语句执行副作用,例如:
document.body.classList.add('loaded')、console.log('init')、localStorage.setItem('flag', '1') - 类或工具函数文件只做定义和导出,不自动执行逻辑;初始化类实例、挂载插件等动作应放在显式调用的函数中,并由业务代码主动触发
CSS、字体、SVG 等资源必须显式排除
"sideEffects": false 会一并移除未被 JS 引用的 CSS 文件(哪怕你在 HTML 中 link 了),因为打包工具默认按 JS 模块图分析。解决方法是把它们加进白名单:
- 如果你用
import './index.css'方式加载样式,就得写:"sideEffects": ["*.css", "*.scss", "*.svg"] - 若只有个别 JS 文件含副作用(如
src/init.ts注册了全局指令),就精确列出:"sideEffects": ["src/init.ts", "*.css"] - 路径匹配的是构建后的产物路径(即经 Babel/TS 编译后的
.js文件路径),不是源码里的.ts路径
配合构建配置才能真正触发剔除
即使 package.json 写对了,以下配置缺一不可:
- Webpack:必须启用
mode: 'production';开发模式下 Tree Shaking 默认关闭 - 开启
optimization.usedExports: true(标记未使用导出)和minimize: true(交由 Terser 实际删除) - Babel 配置中设
"modules": false,防止import被转成require导致静态分析失效 - TypeScript 的
compilerOptions.module设为"ESNext"或"ES2020",且不启用isolatedModules: false
验证是否真被摇掉最简单的方法
别只看配置,动手测:
- 在某个工具类里加一个明显不用的函数:
export function _UNUSED_HELPER() { alert('I should be gone'); } - 执行生产构建(
npm run build) - 打开
dist/bundle.js,搜索_UNUSED_HELPER或unused harmony export字样 - 若搜不到,说明已成功剔除;若还在,检查它是否被间接引用,或所在文件因副作用未被分析











