避免模块顶层执行副作用,核心是将自动运行代码改为按需调用函数:所有副作用操作须封装进导出函数,禁止在顶层直接执行;通过 init() 函数、环境变量判断或条件逻辑控制初始化时机;纯逻辑与副作用分离;配合 sideEffects 配置提升打包效率。

避免模块顶层执行副作用,核心是把“自动运行”的代码变成“按需调用”的函数。ES 模块一旦被导入,其顶层语句就会立即执行——不管是否用到里面导出的内容。所以关键不是“少写”,而是“不放在顶层”。
把副作用逻辑封装成导出函数
所有可能产生副作用的操作(如 console.log、fetch、DOM 修改、全局赋值)都不要直接写在模块最外层,统一收进具名函数里,只导出函数本身:
- ❌ 错误写法(顶层副作用):
console.log('模块加载了');
export function doSomething() { return 'ok'; } - ✅ 正确写法(无顶层副作用):
export function doSomething() { console.log('模块加载了'); return 'ok'; }
用条件逻辑控制初始化时机
有些逻辑本该只在特定环境或时机触发(比如开发调试、用户登录后),就别让它随模块加载自动跑。可以结合环境变量或状态判断:
- 导出一个 init() 函数,在主应用合适位置手动调用,而不是在模块顶层执行
- 用 if (import.meta.env.DEV) { initDevTools(); } 包裹开发专用逻辑,确保生产构建时该分支被 DefinePlugin 移除
- 避免在模块顶层 new WebSocket() 或 setInterval(),这些会立刻建立连接或启动定时器
拆分关注点:纯逻辑 + 副作用操作分离
把数据处理和外部交互彻底分开,让模块主体保持“纯”:
- 纯计算部分(如格式化、过滤、转换)保留在顶层,它们本身不触发副作用
- 副作用操作(如上报埋点、写 localStorage、渲染 UI)单独抽成函数,由调用方决定是否执行
- 例如:export const formatPrice = (n) => `$${n.toFixed(2)}`;export const trackView = () => ga('send', 'pageview')
借助 sideEffects 配置增强打包器判断
即使你已封装好函数,如果模块所在包未声明无副作用,Webpack 仍可能因保守策略保留整个文件。因此需配合配置:
- 若整个包(如 utils)确实不含任何顶层副作用,package.json 中加 "sideEffects": false
- 若只有部分文件安全(如 logger.js),可写 "sideEffects": ["./src/logger.js"],其余保留
- 项目内单个文件也可在 webpack.config.js 的 rules 中单独设 sideEffects: false
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











