tree-shaking是前端领域一个比较常见的词了,在项目中有什么用呢?这个之前一直没搞明白,通过翻阅众多博文,自己在项目中试验了一下,弄清其大致流程,这里就做了个简单记录。
先看一段代码
// app.js
export function A(a, b) {
return a + b
}
export function B(a, b) {
return a + b
}
// index.js
import {A} from '/app.js'
A(1, 2)
// 当index.js引用了app.js的A函数,如果tree-shaking起了作用,B函数是不会被打包进最后的bundle的。
然鹅,在webpack的官网有一句话: rlies on the structure of ES2015 modules syntax , i.e.import an export,翻译一下就是tree-shaking依赖ES6的模块输入输出语法,如果你的模块引入方式是require等,tree-shaking是不会起作用的。
在开发打包中,我们常用的是babel, webpack,uglifyJs这三样神器,而tree-shaking就是在第一步起作用的,在webpack对js文件处理的过程中,先是babel-loader去处理js文件,处理过后,webpack进行打包处理,最后由ugligyJs进行代码压缩。babel的配置文件中有一项配置很关键,就是preset:
{
"presets": [
["env", {
"modules": false //关键点
}],
"stage-2",
"react"
]
}
在这个配置里面env的options中有一个modules: false,这个是指示babel如何去处理import和export的关键,默认处理成require形式,如果加上此option,那么babel就不会把import转变成requier形式,为webpack进行tree-shaking创造了条件。
综上所述,简单来说tree-shaking就是删除项目中无用的代码,压缩项目体积。
webpack对文件tree-shaking的过程如下:
在认定某块无用后,会在处理过后写下一段注释,uglifyJs会根据这段注释去删除代码
function(module, exports, __webpack_require__) {
/* harmony export */ exports["foo"] = foo;
/* unused harmony export bar */;
function foo() {
return 'foo';
}
function bar() {
return 'bar';
}
}
在tree-shaking学习的过程中,可以对class进行tree-shaking,是比较有意思的,找了一个demo,支持tree-shaking:
1.首先使用loader去处理,实验阶段的代码,编译成es代码,这样webpack内部的编译器才能正确识别代码。
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['babel-preset-stage-2', 'babel-preset-react']
}
},
'eslint-loader'
],
exclude: /node_modules/
}
]
}
2.通过webpack打包,并对代码进行tree-shaking,在打包完成的bundle后,和输出的文件之前,对最后的bundle进行兼容性处理。
plugins: [
new UglifyJSPlugin(), // uglify要在babelPugin的前面
new BabelPlugin({ //在这个插件内部进行最后bundle的兼容性处理
test: /\.js$/,
babelOptions: {
presets: [env]
}
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new HtmlWebpackPlugin({
template: 'index.html'
}),
]
最后总结步骤:
1.先编译实验性质代码为标准代码,会涉及到babel-preset-stage-x插件
2.webpack打包代码并进行tree-shaking识别
3.uglifyjs进行代码压缩,并根据webpack标识删除多余代码
4.对最后的代码进行兼容性处理涉及到babel-preset-env插件
第三方类库的tree-shaking
在研究了许多第三方类库后,基本得出的结论是,tree-shaking是不能对大部分的第三方类库进行的。