前言
在实际配置Webpack
过程中总会遇到一些坑,Tree-shaking
就是其中之一,按照教程中一步步配置,你会发现配了半天还是不生效,本文
就是为了解决这个问题而写,希望看到这篇文章的同学能少走一些弯路。
什么是Tree-shaking
Tree-shaking
是Webpack
用来删除冗余代码的一种手段,那冗余代码又是指什么,请看以下代码:
// ~index.js
import { foo } from './content.js';
foo();
// ~content.js
export function foo() {
alert('I am foo');
}
// 没有被index.js引入,为冗余代码
export function bar() {
alert('I am bar');
}
函数bar
由于没有被引用,因此bar
为冗余代码。通过使用Tree-shaking
,让bar
在打包的时候自动被删除掉,从而减少了代码的构建体积。
如何配置
1、在package.json文件中将sideEffects设为false
sideEffects
设为false
,告诉Webpack
没有文件有副作用,所有文件都可以Tree-shaking
,这样会识别全局导入css为无用代码,造成全局导入css
被删除。例:import'./styke.css'
,打包后style.css
会被删除,为了解决这个问题,可在css
相关loader
重新设为true
。sideEffects
为true
表示文件有副作用,不可以Tree-shaking
。
// ~package.json
{
"name": "webpackdemo",
"version": "1.0.0",
"author": "dengshangli",
"license": "ISC",
"description": "",
"sideEffects": false,
...
}
2、将css相关loader中sideEffects设为true
sideEffects
设置为true
,Webpack
会将css
代码识别为有副作用,避免Tree-sahking
执行全局import 'styles.css'
失效。
// ~webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
//开启css模块化
modules: { localIdentName: '[path][name]__[local]--[hash:base64:5]' },
sourceMap: true,
},
},
'postcss-loader'
],
}),
// 将css代码识别为有副作用,避免tree-sahking执行全局import 'styles.css'失效
sideEffects: true,
exclude: /node_modules/,
}],
},
...
}
3、使用TerserPlugin,js代码压缩插件
TerserPlugin
为Webpack
内置,无需安装,不使用TerserPlugin
无法冗余代码无法删除成功,Tree-shaking
本身只是为冗余代码添加上标记,真正去除冗余代码是通过压缩工具来进行的。
// ~webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
// 开启js代码压缩,生产环境自动为true
minimize: true,
// 压缩器
minimizer: [
// js代码压缩插件,tree-shaking必须使用
new TerserPlugin(),
...
],
},
...
}
4、让@babel/preset-env不编译ES6模块语句
把modules
设置为 false
,就是告诉 babel
不要编译模块语句,注意,这里不是不编译代码,而是不编译import/export
语句。这会让 Babel 保留我们现有的 ES6 import/export
语句,保留的原因是Tree-shaking
只支持ES6
的模块化导入导出,CommonJs
及其他模块化代码无法删除成功。
// ~.babelrc
{
//babel预设,目的是为了方便配置,集成了多个插件
"presets": [
["@babel/preset-env", { "modules": false }]
],
// babel插件
"plugins": [
"@babel/plugin-transform-runtime"
]
}
注意事项
- 以上配置
Webpack
版本为4.41.5
,理论上4.0
以上就可以 Tree-shaking
只支持ES6
的模块化导入导出Tree-shaking
只有在生产环境中构建才生效
总结
本文只是简单讲解了Tree-shaking
在Webpack
中如何配置,很多细节还没来得及去去深究,例如使用@babel/preset-env
插件预设时将配置项modules
设置为false
,让其不编译ES6
模块语句,那这样在不支持import
语句的浏览器中代码岂不是执行不了,查看构建后的源码发现并不存在import
语句,希望有大神为我解惑。