1. tree shaking (Dead code elimination)
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import
和 export
。这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。
tree shaking 是一种基于 ES Module
规范的 Dead Code Elimination 技术,它会在运行过程中静态分析模块之间的导入导出,确定 ESM
模块中哪些导出值未曾其它模块使用,并将其删除,以此实现打包产物的优化。
2. common.js 和 es6 中模块引入的区别?
CommonJS 是一种模块规范,最初被应用于 Nodejs,成为 Nodejs 的模块规范。运行在浏览器端的 JavaScript 由于也缺少类似的规范,在 ES6 出来之前,前端也实现了一套相同的模块规范 (例如: AMD),用来对前端模块进行管理。自 ES6 起,引入了一套新的 ES6 Module 规范,在语言标准的层面上实现了模块功能。在使用上的差别主要有:
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJs 是单个值导出,ES6 Module可以导出多个
CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
// CommonJS引入模块:require() 是动态的,也意味着我们可以基于条件来导入需要的代码
let dynamicModule;
// 动态导入
if (condition) {
myDynamicModule = require("foo");
} else {
myDynamicModule = require("bar");
}
// ES6 的import是完全静态的, 下面的导入是不可行
if (condition) {
myDynamicModule = require("foo");
} else {
myDynamicModule = require("bar");
}
// 我们只能通过导入所有的包后再进行条件获取
import foo from "foo";
import bar from "bar";
if (condition) {
// foo.xxxx
} else {
// bar.xxx
}
目前浏览器对 ES6 Module 兼容还不太好,我们平时在 Webpack 中使用的 export 和 import,会经过 Babel 转换为 CommonJS 规范。Babel 是一个非常流行的 JavaScript 代码转换器,它能够将高版本的 JS 代码等价转译为兼容性更佳的低版本代码,使得前端开发者能够使用最新的语言特性开发出兼容旧版本浏览器的代码
Babel 可以将 import/export 风格的 ESM 语句等价转译为 CommonJS 风格的模块化语句,但该功能却导致 Webpack 无法对转译后的模块导入导出内容做静态分析
总结:因为tree shaking只能在静态modules下工作。ECMAScript 6 模块加载是静态的,因此整个依赖树可以被静态地推导出解析语法树。所以在 ES6 中使用 tree shaking 是非常容易的。
- ES6 Module引入进行静态分析,故而编译的时候正确判断到底加载了那些模块
- 静态分析程序流,判断那些模块和变量未被使用或者引用,进而删除对应代码