tree-shaking消除大法

174 阅读3分钟

掘金学习资料

Rollup官方文档

Rollup在线测试地址

Tree-shaking的本质就是消除无用的js代码,是基于ES Module进行静态分析,通过AST将用不到的函数进行移除,从而减小打包体积。

如何判断js的代码是无用的?

这些无用的代码又叫Dead Code

  • 代码不可到达,不会执行
  • 代码执行的结果不会被用到
  • 代码中某变量只有写,而没有读操作

Tree-shaking实现的前提

  • 代码必须遵循ES6的模块规范(import & export),如果是CommonJS规范(require)则无法使用
  • 引入模块时就应该避免将内容全部引入,应该局部按需引入才会触发Tree Shaking机制。
  • 确保没有编译器将ESM语法转换成CommonJS语法(这是流行的Babel预设@babel/preset=env的默认行为)

Tree-shaking的工作原理

  1. 解析模块:首先,构建工具会解析所有模块,并构建它们的抽象语法树(AST)表示。
  2. 标记依赖关系:构建工具会分析模块之间的依赖关系,确定哪些模块被导入和使用了。这些依赖关系形成了一个类似于树状结构的图,其中模块之间的依赖关系构成了树的分支。
  3. 标记未使用代码:构建工具会从入口模块开始,沿依赖树向下遍历,并标记那些永远不会被执行的代码块。这些代码块被标记为"未使用"。
  4. 删除未使用代码:最后,构建工具会根据标记的信息删除未使用的代码块,从而生成一个精简的应用包。

Tree-shaking的配置

  1. 在webpack.config.js中配置,在production下,会自动为我们开启tree-shaking
module.exports = {
  mode: "production",
  optimization: {
    usedExports: true,
  },
};
  1. 在package.json中配置 所有导入文件都受tree shaking影响
{ "sideEffects": false }

若需要文件不受影响,只需要把它们添加到列表中就好了,例如:

{
  "sideEffects": ["./src/some-side-effectful-file.js", "*.css"],
}

Tree-shaking注意事项

  1. 副作用(Side Effects):如果模块有副作用(如修改了全局变量或执行了某些操作),那么即使它的导出没有被使用,也不能被Tree Shaking剔除。这时,可以在package.json中通过sideEffects属性来显示指定哪些文件有副作用。
  2. 动态导入:运态导入(通过import()语法)的模块不会被Tree Shaking处理,因为它们的执行时机是不确定的,Webpack无法静态分析它们的使用情况。
  3. 第三方库:并非所有的第三方库都支持Tree Shaking。有的库可能使用了CommonJS模块系统或其他不支持Tree Shaking的语法。在使用这些库时,需要注意它们是否会导致代码体积增加。

Tree shaking的常见使用场景

  1. 减少打包体积:在前端项目中,往往引入许多库、模块或依赖项,但是实际上可能只使用了其中的一部分功能。通过tree shaking,可以识别并删除没有被引用的代码,从而减少最终打包文件的体积,提高加载速度。
  2. 优化生产环境:在生产环境中,性能是至关重要的。通过tree shaking优化,可以确保只有实际被使用的代码被打包进最终的文件中,减少不必要的网络传输和执行时间,降低资源消耗,提升用户体验。
  3. 支持按需加载和懒加载:对于大型的前端应用来说,按需加载和懒加载是一种有效的性能优化手段。Tree shaking可以结合这些技术使用,通过动态import()等方式实现模块的按需加载,进一步减少初始加载时间。
  4. 使用模块化开发:tree shaking主要应用于模块化开发中,通过静态分析代码的使用情况来确定哪些代码是未使用的。