WSの小屋

什么是Tree-shaking?

tree——树,shaking——摇动,Tree-shaking意为“摇树优化”。

前端中的 tree-shaking 可以理解为通过工具"摇"我们的 JS 文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。

具体来说,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块 code 摇掉,这样来达到删除无用代码的目的。

Tree-shaking其实就是:把无用的模块进行“剪枝”,很多没有用到的API就不会打包到最后的包里

Tree-Shaking 是为了 Dead code elimination,这是编译器原理中常见的一种编译优化技术,简单来说就是消除无用代码(Dead code)。

Dead code

Dead code,也叫死码,无用代码,它的范畴主要包含了以下两点,

  • 不会被运行到的代码(unreachable code)
  • 只会影响道无关程序运行结果的变量(Dead Variables)

在传统的静态编程语言编译器中,编译器可以判断出某些代码根本不影响输出,我们可以借助编译器将 Dead Code 从 AST(抽象语法树)中删除,但 JavaScript 是动态语言,编译器不能帮助我们完成死码消除,我们需要自己实现 Dead code elimination。
而我们说的 Tree-Shaking,就是 Dead code elimination 的一种实现,它借助于 ECMAScript 6 的模块机制原理,更多关注的是对无用模块的消除,消除那些引用了但并没有被使用的模块。

ECMAScript 6 module

JavaScript 的模块化经历一个漫长的发展历程,我们知道刚开始 JavaScript 是没有模块的概念的,最初我们只能借助 IIFE 尽量减少对全局环境的污染,后来社区出现了用于浏览器端的以 RequireJS 为代表的 AMD 规范和以 Sea.js 为代表的 CMD 规范,服务器端也出现了 CommonJS 规范,再后来 JavaScript 原生引入了 ES Module,取代社区方案成为浏览器端一致的模块解决方案。

ES Module 现在也可以用于服务器,Node.js 在 v12.0.0 版本实现了对 ES Module 的支持。
对于 ES Module 基础语法不了解的可以参考下面的文章,我们接下来主要理解它的机制,

  • Introduction to ES Modules
  • ECMAScript 6 入门,Module 语法
  • JavaScript modules | MDN

对比是理解知识非常有效的一种手段。我们通过对比 ES Module 与 CommonJS 的区别来理解 ES Module 的模块机制,它们的区别主要体现在模块的输出和执行上,

  • ES Module 输出的是值的引用,而 CommonJS 输出的是值的拷贝
  • ES Module 是编译时执行,而 CommonJS 模块是在运行时加载

所以 ES Module 最大的特点就是静态化,在编译时就能确定模块的依赖关系,以及输入和输出的值,这意味着什么?意味着模块的依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,正是基于这个基础,才使得 Tree-Shaking 成为可能,这也是为什么 rollup 和 Webpack 2 都要用 ES6 Module 语法才能支持 Tree-Shaking。

Tree-shaking 的原理

借助静态模块分析,Tree-Shaking 实现的大体思路:借助 ES6 模块语法的静态结构,通过编译阶段的静态分析,找到没有引入的模块并打上标记,然后在压缩阶段利用像 uglify-js 这样的压缩工具删除这些没有用到的代码。

参考链接

Tree Shaking:从原理到实现

Comments | 0条评论