未加星标

关于Tree Shaking

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二05 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

Tree Shaking是一个术语,字面的理解就是摇一摇树,树上的枯叶就会掉下来,留下绿叶。

Rich Harris 的模块打包器 Rollup 普及了 javascript 圈内一个重要的特性:Tree shaking,即是指消除JavaScript上下文中无用代码,或更精确地说,只保留有用的代码。它依赖于ES6模块 import / export 模块系统的 静态结构(static structure) 来检测哪一个模块没有被使用,因为,import 和 export 不会在运行时改变。说的再直白一点就是Tree shaking 从模块包中排除未使用的 exports 项。

webpack 2 内置引入的 Tree-shaking 代码优化技术。

示例

看一下官方文档提供的示例:

考虑一个 maths.js 库文件导出两个函数, square 和 cube :

// 这个函数不在任何地方被使用 export function square(x) { return x * x; //平方 } // 这个函数被其他脚本使用 export function cube(x) { return x * x * x; //立方 }

在我们的 main.js 中,我们选择性地导入 cube :

import {cube} from './maths.js'; console.log(cube(5)); // 125 运行 node_modules/.bin/webpack main.js dist.js 并检查 dist.js 显示没有导出 square ,请查看 “unused harmony export square”的注释,再查看 /* harmony export (immutable) */ __webpack_exports__["a"] = cube; 这条语句,显示这里只导出了 cube : /* ... webpackBootstrap ... */ /******/ ([ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* unused harmony export square */ /* harmony export (immutable) */ __webpack_exports__["a"] = cube; // This function isn't used anywhere function square(x) { return x * x; } // This function gets included function cube(x) { return x * x * x; } /***/ }), /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__maths_js__ = __webpack_require__(0); console.log(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__maths_js__["a" /* cube */])(5)); // 125 /***/ })

当运行生产环境构建, node_modules/.bin/webpack --optimize-minimize main.js dist.min.js 时,只保留了 cube 的压缩版本,而 square 并没有保留在构建的 bundle 中:

/* ... */ function(e,t,n){"use strict";function r(e){return e*e*e}t.a=r} /* ... */ function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(0);console.log(n.i(r.a)(5))} 讨论

大家可以看看关于Tree Shaking 的讨论: 如何评价 Webpack 2 新引入的 Tree-shaking 代码优化技术?

赞同尤雨溪的观点

指出的一点就是不管是 rollup 还是 webpack 2,tree-shaking 都是因为 ES6 modules 的静态特性才得以实现的。ES6 modules 的 import 和 export statements 相比完全动态的 CommonJS require,有着本质的区别。举例来说:

1. 只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面。(ECMA-262 15.2)

2. import 的模块名只能是字符串常量。(ECMA-262 15.2.2)

3. 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。换句话说,ES6 imports are hoisted。(ECMA-262 15.2.1.16.4 8.a)

4. import binding 是 immutable 的,类似 const。比如说你不能 import { a } from ‘./a’ 然后给 a 赋值个其他什么东西。(ECMA-262 15.2.1.16.4 12.c.3)

这些设计虽然使得灵活性不如 CommonJS 的 require,但却保证了 ES6 modules 的依赖关系是确定 (deterministic) 的,和运行时的状态无关,从而也就保证了 ES6 modules 是可以进行可靠的静态分析的。对于主要在服务端运行的 Node 来说,所有的代码都在本地,按需动态 require 即可,但对于要下发到客户端的 web 代码而言,要做到高效的按需使用,不能等到代码执行了才知道模块的依赖,必须要从模块的静态分析入手。这是 ES6 modules 在设计时的一个重要考量,也是为什么没有直接采用 CommonJS。

正是基于这个基础上,才使得 tree-shaking 成为可能(这也是为什么 rollup 和 webpack 2 都要用 ES6 module syntax 才能 tree-shaking),所以说与其说 tree-shaking 这个技术怎么了不起,不如说是 ES6 module 的设计在模块静态分析上的种种考量值得赞赏。

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

分页:12
转载请注明
本文标题:关于Tree Shaking
本站链接:http://www.codesec.net/view/530743.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(84)