什么是 Tree-Shaking
用来在打包编译成 bundle 时消除 ES6 Module 语法中未使用到的代码和模块。
What is tree shaking? 🌲
Tree-Shaking 的作用
用于跨文件代码的 DCE 优化。
依赖 ES6 module 特性。
消除未被 import 的 export 模块。
对 Function 函数模块的处理效果好。
无法直接处理 Class 模块。
什么是 Dead Code Elimination
DCE 用来消除不能执行的代码 Dead Code。
javascript 常用 uglify 来 DCE 。
只能清除单文件里的 Dead Code (只读不写,结果用不到,不被执行)
应该怎么实践 Tree-Shaking
三方库按需加载。
import map from "lodash/map";
import { Input, Button } from "atnd"; // 需要使用 babel 按需加载 plugin
按需加载的实现
不要写奇怪含有副作用的代码。副作用wiki
良好的模块拆分和设计才是关键。
CommonJS 和 ES6 Module
CommonJS require
动态加载,执行后才知道结果。
ES6 Module import
静态分析,不需要执行即可通过字面量对代码分析。
打包工具的 Tree-Shaking
Rollup 只处理函数和顶层 import / export
导入的变量
Rollup 结果比 Webpack 更优化点
Dead Code
- 死区代码,被赋值但在后续执行中未使用的变量(Dead store)
function func(a, b) {
var x;
var i = 300;
while (i--) {
x = a + b; // Dead store
}
}
- 曾经使用但现在未使用到的代码(Oxbow code)
function temp() {
function private_calculation() {
return 22;
}
this.calc = function () {
// private_calculation()
return 22;
}
}
- 无法到达的代码: 执行不了的判断,执行不到的循环,return 后的代码(Unreachable code)
// 执行不了的判断
function temp() {
var a = 2;
if (a > 3) {
return 3; // Dead Code
}
}
// return 后的代码
function temp() {
return 1;
var a = 2; // Dead Code
}
// 执行不到的循环
function temp() {
var a = 2;
while (false) {
return 3; // Dead Code
}
}
- 无用的 <script src="" > 资源链接
Webpack Rollup 配置 Tree-Shaking
Rollup 配置
import babel from 'rollup-plugin-babel'
import uglify from 'rollup-plugin-uglify'
export default {
entry: 'src/main.js',
dest: 'rollup.bundle.js',
format: 'cjs',
treeshake: true,
plugins: [
babel(),
uglify()
]
}
Webpack 配置
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: path.join(__dirname, 'src/main.js'),
output: {filename: 'webpack.bundle.js'},
module: {
rules: [
{
test: /\.js$/,
loaders: 'babel-loader'
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: 'production'
}
}),
new webpack.optimize.UglifyJsPlugin({
beautify: false,
comments: false,
compress: {
warnings: false,
collapse_vars: true,
reduce_vars: true
}
}),
new webpack.optimize.ModuleConcatenationPlugin()
]
}
总结
Tree-Shaking 是用来在打包编译前消除 es6 module 中未使用的代码模块的功能。
打包工具用 webpack 和 rollup 来实现,只能对 export 导出的函数代码和模块进行优化。
相比 DCE Tree-Shaking 属于广义的 DCE,传统 DEC 只能清除单文件中不可执行不可到达的代码,Tree-Shaking 是跨文件依赖于 es6 module 导入静态分析的。
commonjs 规范属于动态导入,代码不执行到 require 是无法知道执行的结果的,es6 module 的 import 属于静态分析,通过导入的字面量即可分析模块代码。
网友评论