Rollup如何实现Tree Shaking,有哪些技巧?
- 内容介绍
- 文章标签
- 相关推荐
图啥呢? Ru果你曾为 JavaScript 包体积膨胀而抓狂, 或在上线后主要原因是加载慢而被用户投诉,那么你一定对“摇树”这件事充满好奇。Rollup 作为首批把摇树写进核心的打包工具,它的实现方式既简洁又让人惊叹。本文将从底层原理出发, 配合真实案例,手把手教你玩转 Rollup 的摇树功能,让你的产物像经过精雕细琢的艺术品一样轻盈。
Rollup 的 Tree Shaking 原理
不靠谱。 Rollup 在读取每个入口文件后会使用把源码解析成 AST。这棵抽象语法树记录了所有变量声明、函数定义以及 import / export 语句的位置。
有了 AST, Rollup 能在不运行代码的情况下追踪每个标识符到底是从哪儿来、去向何处。这种静态分析能力是 Tree Shaking 的核心基础。
Tree Shaking 的核心机制
在现代前端生态里 ES Module 已经成为主流。它天生具备静态结构,编译时就能明确每个导入导出的关系。借助这种特性, 绝绝子... 构建工具可以在打包阶段“看见”哪些代码真的会被施行,从而把那些永远不会跑到浏览器里的死代码直接剔除。
从 src/main.js 出发, Rollup 会递归读取每条 import … from … 语句,把对应文件加入依赖图。当所有节点都被收集完毕后我们得到一张完整的模块网络,换个思路。。
琢磨琢磨。 有了依赖图后 Rollup 从入口开始向回走——只要某个导出被其他模块引用,就给它贴上“活”的标签。未被标记的导出会被视作死代码。
Tree Shaking 的实际应用
就这? 在上面的场景里 unused 没有任何引用路径指向它,所以在生成阶段会被彻底抹掉。
Rollup Neng在不运行代码的情况 又爱又恨。 下追踪每个标识符到底是从哪儿来、去向何处。
1. 使用 export default 与具名导出的混搭
默认导出同样可以被摇掉,只要没有任何 import 指向它即可。但请避免一边出现大量未使用的具名导出,这会让分析器产生额外负担。
2. 动态导入导致失效
没耳听。 像 { ...utils } 这种写法, 在编译阶段无法确定实际使用了哪些成员,请改用具名导入或显式列举需要的成员。
3. CommonJS 模块
如果直接引入一个仅提供 CJS 导出 = require` 的库, 即使使用了插件转化,也可能留下大量未清理的代码。推荐使用对应的 ESM 包,比方说 Lodash-es 替代 lodash,摆烂...。
4. 副作用文件
CSS、全局 polyfill 等文件往往会在顶部施行副作用。 火候不够。 可在项目根目录下的 package.json 添加:
{ "sideEffects": }
或者直接设为 false 并自行管理这些副作用。
5. 使用 @rollup/plugin-commonjs 插件
谨记... 所有第三方依赖均转为 ESM, 并告知 Rollup 大多数第三方库没有副作用,从而进一步清理无用代码。
6. 使用 terser 插件
此时如果你再加上 @rollup/plugin-terser到头来产物往往比手写的 ES5 代码还要紧凑。
7. 避免顶层施行副作用
避免所有顶层施行副作用, 保持每个组件都是具名导出,以便 Rollup 能精准判断引用路径。
8. 对动态属性访问进行重构
对单个文件进行细粒度控制;
9. 开启 terser 并根据项目需求调整 compress 配置
在 CI 中检测 bundle 大小变化, 确保优化持续有效
10. 在 package.json 中声明 sideEffects
若不声明 sideEffects,将整个库一次性 export *,可能导致大量未清理的代码,梳理梳理。。
实际案例
某电商后台系统采用 Rollup 打包内部 UI 库, 每个页面只用到几百行组件代码,却主要原因是一次性引入整个库导致首屏体积超过 120KB。下面展示我们是如何一步步削减体积的:,不忍卒读。
优化前
在 package.json 中添加:
{ "sideEffects": false }
优化后
不地道。 完成后用 Chrome DevTools 检测 bundle 大小,从原来的 120KB ↓至≈38KB
Rollup 配置示例
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollul-plugin-terser';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.min.js',
format: 'esm',
sourcemap: true
},
plugins: ,
treeshake: {
moduleSideEffects: false
}
};
Tree Shaking 参数说明
moduleSideEffects: 对单个文件进行细粒度控制;
恳请大家... propertyReadSideEffects: 当读取对象属性时是否保留副作用。
通过上述四步流程, 你可以让 Rollup 像一位细致匠人,把不需要的枝桠全部砍掉, 往白了说... 只留下最核心、最精炼的部分送达浏览器。
图啥呢? Ru果你曾为 JavaScript 包体积膨胀而抓狂, 或在上线后主要原因是加载慢而被用户投诉,那么你一定对“摇树”这件事充满好奇。Rollup 作为首批把摇树写进核心的打包工具,它的实现方式既简洁又让人惊叹。本文将从底层原理出发, 配合真实案例,手把手教你玩转 Rollup 的摇树功能,让你的产物像经过精雕细琢的艺术品一样轻盈。
Rollup 的 Tree Shaking 原理
不靠谱。 Rollup 在读取每个入口文件后会使用把源码解析成 AST。这棵抽象语法树记录了所有变量声明、函数定义以及 import / export 语句的位置。
有了 AST, Rollup 能在不运行代码的情况下追踪每个标识符到底是从哪儿来、去向何处。这种静态分析能力是 Tree Shaking 的核心基础。
Tree Shaking 的核心机制
在现代前端生态里 ES Module 已经成为主流。它天生具备静态结构,编译时就能明确每个导入导出的关系。借助这种特性, 绝绝子... 构建工具可以在打包阶段“看见”哪些代码真的会被施行,从而把那些永远不会跑到浏览器里的死代码直接剔除。
从 src/main.js 出发, Rollup 会递归读取每条 import … from … 语句,把对应文件加入依赖图。当所有节点都被收集完毕后我们得到一张完整的模块网络,换个思路。。
琢磨琢磨。 有了依赖图后 Rollup 从入口开始向回走——只要某个导出被其他模块引用,就给它贴上“活”的标签。未被标记的导出会被视作死代码。
Tree Shaking 的实际应用
就这? 在上面的场景里 unused 没有任何引用路径指向它,所以在生成阶段会被彻底抹掉。
Rollup Neng在不运行代码的情况 又爱又恨。 下追踪每个标识符到底是从哪儿来、去向何处。
1. 使用 export default 与具名导出的混搭
默认导出同样可以被摇掉,只要没有任何 import 指向它即可。但请避免一边出现大量未使用的具名导出,这会让分析器产生额外负担。
2. 动态导入导致失效
没耳听。 像 { ...utils } 这种写法, 在编译阶段无法确定实际使用了哪些成员,请改用具名导入或显式列举需要的成员。
3. CommonJS 模块
如果直接引入一个仅提供 CJS 导出 = require` 的库, 即使使用了插件转化,也可能留下大量未清理的代码。推荐使用对应的 ESM 包,比方说 Lodash-es 替代 lodash,摆烂...。
4. 副作用文件
CSS、全局 polyfill 等文件往往会在顶部施行副作用。 火候不够。 可在项目根目录下的 package.json 添加:
{ "sideEffects": }
或者直接设为 false 并自行管理这些副作用。
5. 使用 @rollup/plugin-commonjs 插件
谨记... 所有第三方依赖均转为 ESM, 并告知 Rollup 大多数第三方库没有副作用,从而进一步清理无用代码。
6. 使用 terser 插件
此时如果你再加上 @rollup/plugin-terser到头来产物往往比手写的 ES5 代码还要紧凑。
7. 避免顶层施行副作用
避免所有顶层施行副作用, 保持每个组件都是具名导出,以便 Rollup 能精准判断引用路径。
8. 对动态属性访问进行重构
对单个文件进行细粒度控制;
9. 开启 terser 并根据项目需求调整 compress 配置
在 CI 中检测 bundle 大小变化, 确保优化持续有效
10. 在 package.json 中声明 sideEffects
若不声明 sideEffects,将整个库一次性 export *,可能导致大量未清理的代码,梳理梳理。。
实际案例
某电商后台系统采用 Rollup 打包内部 UI 库, 每个页面只用到几百行组件代码,却主要原因是一次性引入整个库导致首屏体积超过 120KB。下面展示我们是如何一步步削减体积的:,不忍卒读。
优化前
在 package.json 中添加:
{ "sideEffects": false }
优化后
不地道。 完成后用 Chrome DevTools 检测 bundle 大小,从原来的 120KB ↓至≈38KB
Rollup 配置示例
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollul-plugin-terser';
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.min.js',
format: 'esm',
sourcemap: true
},
plugins: ,
treeshake: {
moduleSideEffects: false
}
};
Tree Shaking 参数说明
moduleSideEffects: 对单个文件进行细粒度控制;
恳请大家... propertyReadSideEffects: 当读取对象属性时是否保留副作用。
通过上述四步流程, 你可以让 Rollup 像一位细致匠人,把不需要的枝桠全部砍掉, 往白了说... 只留下最核心、最精炼的部分送达浏览器。

