Webpack 与 Rollup 中 Tree-shaking 的实现原理与效果

 更新时间:2026年03月09日 09:17:44   作者:拉不动的猪  
Tree-shaking是现代前端构建工具中用于消除死代码的重要优化手段,本文就来介绍一下Webpack 与 Rollup 中 Tree-shaking 的实现原理与效果,具有一定的参考价值,感兴趣的可以了解一下

Tree-shaking 是现代前端构建工具中用于消除死代码(未被使用的代码)的重要优化手段,核心原理是利用 ES6 模块的静态特性(import/export)分析代码依赖,剔除未被引用的导出内容。

一、Tree-shaking 核心前提

Tree-shaking 仅对 ES6 模块(ESM)  有效,因为 ESM 具有以下静态特性:

  • 模块依赖关系在编译时确定(而非运行时)。
  • import/export 语句只能出现在模块顶层,无法动态修改。

CommonJS 模块(require/module.exports)因依赖关系动态化,无法被 Tree-shaking 优化。

二、Rollup 中的 Tree-shaking

Rollup 是专注于 ES 模块打包的工具,Tree-shaking 是其原生核心功能,实现简洁且高效。

1. 实现原理

Rollup 通过以下步骤实现 Tree-shaking:

  1. 依赖解析:遍历模块的 import/export 语句,构建模块依赖图。
  2. 标记未使用代码:从入口模块出发,追踪所有被引用的导出(export),未被引用的导出被标记为 “死代码”。
  3. 删除死代码:在打包阶段直接剔除标记的死代码,不生成冗余内容。

Rollup 对代码的静态分析更彻底,且默认输出未被混淆的代码,因此 Tree-shaking 效果直观可见。

2. 代码示例与效果

源文件

// utils.js(ES 模块)
export const add = (a, b) => a + b;
export const minus = (a, b) => a - b; // 未被使用的函数

// index.js(入口文件)
import { add } from './utils.js';
console.log(add(1, 2)); // 仅使用 add

Rollup 配置(rollup.config.js)

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es' // 输出 ES 模块(保留 import/export,便于观察)
  }
};

打包结果(dist/bundle.js)

const add = (a, b) => a + b;
console.log(add(1, 2));
  • 效果:未被使用的 minus 函数被完全剔除,输出代码简洁。

三、Webpack 中的 Tree-shaking

Webpack 从 v2 开始支持 Tree-shaking,但实现逻辑更复杂,受多种因素影响(如模式、压缩工具等)。

1. 实现原理

Webpack 的 Tree-shaking 分为三个阶段:

  1. 标记阶段

    • 解析 ES 模块的 import/export,通过 ModuleConcatenationPlugin 分析模块依赖。
    • 对未被引用的导出标记为 /* unused harmony export xxx */(仅标记,不删除)。
  2. 删除阶段

    • 依赖 压缩工具(如 Terser)  剔除标记的死代码。
    • 仅在 production 模式下默认启用(开发模式为保留代码不删除)。
  3. 副作用处理

    • 通过 package.json 的 sideEffects 字段标记模块是否有副作用(如全局变量修改、DOM 操作),避免误删有副作用的代码。

2. 代码示例与效果

源文件(同 Rollup 示例)

// utils.js
export const add = (a, b) => a + b;
export const minus = (a, b) => a - b; // 未被使用

// index.js
import { add } from './utils.js';
console.log(add(1, 2));

Webpack 配置(webpack.config.js)

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  mode: 'production' // 必须为 production 模式才会删除死代码
};

打包结果(dist/bundle.js,简化后)

console.log(3); // add(1,2) 被直接计算,minus 完全删除
  • 效果:未被使用的 minus 被剔除,且 add 函数因逻辑简单被进一步优化(直接计算结果)。

3. 关键配置:sideEffects

如果模块存在副作用(如修改全局变量),需在 package.json 中声明,避免被误删:

json

{
  "sideEffects": [
    "./src/polyfill.js", // 有副作用的模块
    "*.css" // CSS 文件通常有副作用(插入样式)
  ]
}
  • sideEffects: false:表示所有模块均无副作用,可安全删除未引用代码。

四、核心差异对比

特性RollupWebpack
分析能力原生支持 ESM 静态分析,更彻底需依赖插件(ModuleConcatenationPlugin),分析逻辑较复杂
删除死代码时机打包阶段直接删除依赖压缩工具(Terser)在优化阶段删除
开发模式效果即使开发模式也会删除死代码仅 production 模式删除(开发模式保留用于调试)
输出可读性输出代码接近源码,Tree-shaking 效果直观输出代码经压缩混淆,效果需反推
适用场景库文件打包(如工具库、组件库)应用程序打包(依赖复杂、需处理多种模块类型)

五、总结

  • Rollup:Tree-shaking 实现简洁高效,输出代码干净,适合库文件打包(如 React、Vue 等)。
  • Webpack:Tree-shaking 需配合压缩工具和模式配置,功能更全面(支持多种模块类型、复杂依赖),适合应用程序打包。

六、直观点

  • 整个过程就像 “清理房间”:先摸清房间里的物品(依赖解析)→ 标记没用的垃圾(标记死代码)→ 直接扔掉垃圾(删除死代码);
  • 对比 Webpack :Rollup 是 “边打包边扔垃圾”,Webpack 是 “先标记垃圾,最后找清洁工(Terser)扔”,所以 Rollup 的产物更直观看到剔除效果。

到此这篇关于Webpack 与 Rollup 中 Tree-shaking 的实现原理与效果的文章就介绍到这了,更多相关Webpack Rollup Tree-shakin实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS 仿腾讯发表微博的效果代码

    JS 仿腾讯发表微博的效果代码

    这篇文章主要介绍了JS 仿腾讯发表微博的效果代码,有需要的朋友参考一下
    2013-12-12
  • JavaScript实现瀑布动画

    JavaScript实现瀑布动画

    这篇文章主要为大家详细介绍了JavaScript实现瀑布动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • js canvas实现圆形流水动画

    js canvas实现圆形流水动画

    这篇文章主要为大家详细介绍了js canvas实现圆形流水动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • javascript静态的url如何传递

    javascript静态的url如何传递

    javascript静态的url如何传递...
    2007-05-05
  • 详解JavaScript中的Unescape()和String() 函数

    详解JavaScript中的Unescape()和String() 函数

    这篇文章主要介绍了详解JavaScript中的unescape()和String() 函数,JavaScript unescape() 函数可对通过 escape() 编码的字符串进行解码,String() 函数把对象的值转换为字符串,对本文感兴趣的朋友一起学习吧
    2015-11-11
  • 浅析js实现网页截图的两种方式

    浅析js实现网页截图的两种方式

    这篇文章主要介绍了浅析js实现网页截图的两种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • 生产制造追溯系统之再说条码打印

    生产制造追溯系统之再说条码打印

    这篇文章主要介绍了生产制造追溯系统之再说条码打印,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-06-06
  • JS数组求和的常用方法总结【5种方法】

    JS数组求和的常用方法总结【5种方法】

    这篇文章主要介绍了JS数组求和的常用方法,结合实例形式总结分析了5种数组求和的常见操作方法与相关处理技巧,需要的朋友可以参考下
    2019-01-01
  • JavaScript 箭头函数的特点、与普通函数的区别

    JavaScript 箭头函数的特点、与普通函数的区别

    这篇文章主要介绍了JavaScript 箭头函数的特点、与普通函数的区别,很多情况下,箭头函数和函数表达式创建的函数并无区别,只有写法上的不同,本文第二块内容将介绍箭头函数和普通函数功能上的区别,感兴趣的朋友跟随小编一起看看吧
    2021-11-11
  • JavaScript中iframe实现局部刷新的几种方法汇总

    JavaScript中iframe实现局部刷新的几种方法汇总

    Iframe是一种嵌入网页的框架形式,Web页面可以通过更改嵌入的部分,达到部分内容刷新,通过本文和大家一起学习iframe实现局部刷新的几种方法汇总,对iframe局部刷新相关知识感兴趣的朋友一起学习吧
    2016-01-01

最新评论