Tree Shaking

一、解决的问题

Tree-shaking 去除无用代码,从而减小文件体积。

二、什么是Tree Shaking

Tree-shaking (摇树) 是一个术语,通常指通过打包工具"摇"我们的代码,将未引用代码 (Dead Code) "摇" 掉。在 Webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝,虽然依赖了某些模块,但其实只使用其中的某些方法,通过 Tree Shaking ,将没有使用的方法摇掉,这样来达到删除无用代码的目的。

三、原理

程序会从入口文件出发 ,扫描所有的模块依赖,以及模块的子依赖 ,然后将它们链接 起来形成 一个 "抽象语法树 " (AST)。随后,运行所有代码 ,查看哪些代码是用到过的 ,做好标记 。最后,再将 "抽象语法树"中没有用到的代码"摇落" 。经历这样一个过程后,就去除了没有用到的代码。

前提是模块必须采用 ES6 Module 语法,因为 Tree Shaking 依赖 ES6 的静态语法:import 和 export。不同于 ES6 Module,CommonJS 支持动态加载模块 ,在加载前是无法确定模块是否有被调用 ,所以并不支持 Tree Shaking 。如果项目中使用了 babel 的话, @babel/preset-env 默认将模块转换成 CommonJs 语法,因此需要设置 module:false。

CommonJS 与 ES6 Module 模块的依赖的区别在于,CommonJS 是动态的 ,ES6 Module 是静态的。

CommonJS 导入时,require 的路径参数是支持表达式的,路径在代码执行时是可以动态改变的,所以如果在代码编译阶段就建立各个模块的依赖关系,那么一定是不准确的,只有在代码运行了以后,才可以真正确认模块的依赖关系,因此说CommonJS 是动态的。

ES6 模块不是对象,它的对外接口只是一种静态定义,在代码编译,静态解析阶段就会生成,这样我们就可以使用各种工具对JS模块进行依赖分析,优化代码。

四、sideEffects

webpack v4 开始新增了一个 sideEffects 特性,通过给 package.json 加入 sideEffects: false 声明该包模块是否包含副作用,从而可以为 Tree Shaking 提供更大的优化空间。 举例说明

arduino 复制代码
js
复制代码
// a.js
// 无副作用,仅仅是单纯的 export
function a () {
  console.log('a')
}
export default {
  a
}
javascript 复制代码
js
复制代码
// b.js
function b () {
  console.log('b')
}

// 执行了特殊行为
Array.prototype.fun = () => {}

export default {
  b
}

如果 a 在 import 后未使用,Tree Shaking 完全可以将其优化掉;但是 b 在 import 后未使用,但因为存在他还执行了为数组原型添加了方法,副作用还是会被保留下来 。这时就需要使用 sideEffects: false ,可以强制标识该包模块不存在副作用,那么不管它是否真的有副作用,只要它没有被引用到,整个 模块/包 都会被完整的移除。

如果你的项目中存在一些副作用代码 b 需要被保留下来,比如 polyfill、css、scss、less 等,可以按下面方法一样配置;保证必要的代码不被 Tree Shaking

json 复制代码
json
复制代码
// package.json
{
  "name": "your-project",
  "sideEffects": ["./src/b.js", "*.css"]
}

四、配置条件

  • 使用 ES6 Module 语法(即 import 和 export)。
  • 确保没有 @babel/preset-env等工具将 ES6Module 语法转换为 CommonJS 模块。
  • optimization: { minimize: true, usedExports: true }。
  • 使用支持 Tree Shaking 的包。

五、引用

# 带你了解 Tree Shaking

相关推荐
FungLeo9 小时前
成为全栈·React 管理后台篇·总复盘:从“接口能调通”到“后台值得使用”
前端·react.js·前端框架·项目复盘·成为全栈
Csvn10 小时前
并发模式:让渲染学会排队、插队和让路
前端
可乐鸡翅yeah_10 小时前
新手梳理:M3U8 线上问题,哪些是前端锅,哪些是后端锅
前端·ios·音视频·实时音视频·m3u8·音视频在线播放
Flynt10 小时前
Linear 用 1000 个 PR 换掉 styled-components,我写了 200 个按钮,把这笔账复现了一遍
前端·css·preact
JavaGuide11 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel12 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘13 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马13 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut13 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia12314 小时前
实现完整 Tool Dispatcher
开发语言·前端