什么是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 这样的压缩工具删除这些没有用到的代码。
Comments | 0条评论