Tree Shaking 基于模块级静态分析,不依赖局部作用域;但可通过将副作用移入函数、单函数单文件导出、IIFE 标注 /#__PURE__/ 及合理配置 sideEffects 来提升其效果。

函数的局部作用域本身不直接参与 Tree Shaking,因为 Tree Shaking 是基于模块级静态分析(import/export 关系)进行的,而非运行时作用域。但你可以**巧妙利用局部作用域的封装特性,配合 ES 模块规范和副作用控制,间接提升 Tree Shaking 的准确性和效果**——尤其在大型项目中避免误保留、误排除代码。
明确区分“导出逻辑”与“执行逻辑”
Tree Shaking 会保留整个模块,只要它被 import,且模块顶层存在副作用(如直接调用函数、修改全局变量、DOM 操作等)。而将这些副作用包裹进函数体内,就能让模块顶层“变干净”,从而让打包工具更放心地剔除未被调用的函数。
-
❌ 不推荐(模块顶层有副作用):
import { initLogger } from './logger.js'; initLogger(); // 顶层执行 → 整个 logger 模块无法被 shake -
✅ 推荐(副作用移入函数):
export function setupApp() { initLogger(); mountRoot(); }—— 只要setupApp未被引用,整个模块(含initLogger)就可能被完整移除
拆分高内聚低耦合的“功能函数组”,按需导出
大型项目中常把多个工具函数塞进一个 utils.js,即使只用其中一个,也可能因副作用或导出方式导致整块保留。改用“单函数单文件 + 显式命名导出”,能最大化 Tree Shaking 粒度:
- 每个工具函数独立成文件:
src/utils/uuid.js、src/utils/debounce.js - 统一导出方式:
export function generateUUID() { ... }(不使用export default或对象导出) - 消费端写法:
import { generateUUID } from '@/utils/uuid'—— Webpack/Vite 可精准识别仅需该函数
用 IIFE 包裹副作用代码,并标记 /*#__PURE__*/
当某些初始化逻辑必须存在,又不想因此“污染”模块纯净性时,可将其包装为立即执行函数,并添加 Pure 注释,提示压缩器(如 Terser)该调用可安全删除(若无外部引用):
export const config = { theme: 'dark' };-
/*#__PURE__*/ (() => { console.warn('Theme loaded'); })();—— 若该 IIFE 无返回值、无副作用外溢,Terser 在usedExports启用后可能将其整个擦除 - ⚠️ 注意:仅对真正无副作用的 IIFE 有效;若内部修改了
window.xxx或触发了事件,仍需通过sideEffects字段显式声明
配合 package.json#sideEffects 精准收口
大型项目常含 CSS、字体、SVG 等资源,它们天然有副作用(注入样式表),但不应因此阻止 JS 模块的摇树。合理配置 sideEffects 能让 Tree Shaking “绕过”非 JS 文件,专注清理 JS 逻辑:
-
"sideEffects": ["*.css", "*.scss", "src/styles/**/*"]—— 告诉 Webpack:只有这些是副作用文件,其余 JS 模块可大胆 shake -
"sideEffects": false—— 表示项目中所有模块都无副作用(极简场景可用,但需严格自检) - 避免写
"sideEffects": ["*"],这等于关闭 Tree Shaking

















