ES6 module 静态结构
当前的JavaScript模块格式具有动态结构:导入和导出的内容可以在运行时(runtime)更改。 ES6引入自己的模块格式的一个原因是启用静态结构
。静态结构
意味着您可以在编译时
确定导入和导出(静态) --- 您只需要查看源代码,而不必执行它。 ES6在语法上强制执行:您只能在顶层导入和导出
(而不嵌套在条件语句中), 并且导入和导出语句没有动态部分(不允许使用变量等)。
对比没有静态结构的CommonJS模块
如下代码,只有运行代码的时候才能知道导入的内容;
var my_lib;
if (Math.random()) {
my_lib = require('foo');
} else {
my_lib = require('bar');
}
同样,也只有在运行代码的时候才能知道导出的内容
if (Math.random()) {
exports.baz = function baz(){};
}
ES6 模块 export import
export function add(){
}
import react from 'react'
ES6模块的灵活性较差,迫使我们保持静态,因此有如下好处:
- 在捆绑期间消除死代码,优化打包之后的代码体积(Tree-Shaking)
- 紧凑捆绑,没有自定义捆绑格式
- 更快查找到入口 (commonjs必须执行才能查找,很慢,因为是动态的)
- 效益:变量检查(静态的知道哪些变量在模块内的哪些位置可见)
- 为类型做好准备(静态类型检查加强)
什么是Tree-Shaking?
Tree-Shaking是一个术语,通常用于描述移除Javascript上下文中的未引用的代码(dead-code)。它依赖于ES6 module语法的静态结构特性,如 import 和 export ,用来检测代码模块是否被导出、导入,且被Javascript文件使用。使用模块打包(webpack,rollup)将多个Javascript文件打包为单文件时自动删除未引用的代码。对于发布线上代码起到优化作用。这个术语和概念实际是由ES2015模块打包工具rollup普及起来的。
tree-shaking
更关注于无用模块的消除,消除那些引用了但并没有被使用的模块。DCE 消灭不可能执行的代码。
在webpack 2
正式版内置支持ES6模块和未使用模块检测能力。新的webpack 4
正式版本扩展了此检测能力,通过 package.json
的"sideEffects"
属性作为标记,向compiler
提供提示,表明项目中的哪些文件是" pure(纯 ES2015 模块) ",由此可以安全的删除文件中未使用的部分。
使用Tree-Shaking 压缩代码(webpack 4)
webapck.config.js
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'budle.js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
usedExports: true
}
}
将文件标记为 side-effect-free(无副作用)
:提示 webpack compiler
哪些代码是“纯粹部分”,通过 package.json
的 "sideEffects"
属性,来实现这种方式
{
"name": "webpack-4-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.35.0",
"webpack-cli": "^3.3.5",
"webpack-dev-server": "^3.7.2",
"webpack-merge": "^4.2.1"
},
"sideEffects": false
}
结论
想要使用tree shaking
必须注意如下几点:
- 使用es6 模块语法(import 和 export)
- 确保没有compiler将ES6模块语法转换为CommonJS模块(Babel preset 中 @babel/preset-env 的默认值是auto,将module 设置为false将不会转换模块)
- 在项目
package.json
文件中,添加一个"sideEffects"
属性 - 通过将
mode
选项设置为production
,启用minification(代码压缩)
和tree shaking
。
你可以将应用程序想象成一棵树,绿色表示实际用到的 source code(源码) 和 library(库),是树上活的树叶。灰色表示未引用代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。
使用方法可以查下一篇文章:webpack 4 中 tree shaking 生产环境配置
参考:
https://exploringjs.com/es6/ch_modules.html#static-module-structure
https://developer.mozilla.org/zh-CN/docs/Glossary/Tree_shaking
https://webpack.docschina.org/guides/tree-shaking/#src/components/Sidebar/Sidebar.jsx
https://juejin.im/post/5a4dc842518825698e7279a9
网友评论