前言
在实际配置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语句,希望有大神为我解惑。