webpack4之SplitChunksPlugin配置、Prefetching配置、css打包分离


SplitChunksPlugin

目的

三方引入的依赖包,其实基本不会被改动,其实不需要和业务代码一起打包到一个js文件中。所以业务代码和依赖包可以进行分开,每次打包的时候,用户只需要更新业务代码,依赖包可以从缓存中读取。

配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// index.js
import _ from 'lodash'
console.log(_.join(['a', 'b'], '##'))

// webpack.config.js
module.exports = {
mode: 'production',
devtool: 'cheap-module-eval-source-map',
entry: {
index1: './index.js'
},
plugins: [new HtmlWebpackPlugin({
template: './index.html'
}), new CleanWebpackPlugin()
],
optimization: {
splitChunks: { // 告诉webpack,我要进行代码分割
chunks: "all", // 同步异步加载都需要进行分割,一般只需要写这一个配置就行了,下面的都可以不用写
minSize: 30000, // 对依赖包大于30K的才进行分割
minChunks: 1, // 对依赖包引入了几次了才进行代码分割
maxAsyncRequests: 5, // 最大对前5个依赖包进行代码分割
maxInitialRequests: 3, // 对入口文件引入的依赖包进行代码分割
automaticNameDelimiter: '~', // 连接符
name: true,
cacheGroups: { // 缓存组的意思
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10 // 优先级,都符合vendors和default的时候看哪个优先级高
},
default: {
priority: -20, // 优先级
reuseExistingChunk: true
}
}
}
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'sef')
}
}
针对异步加载依赖包,不配置webpack也会进行代码分割
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// index.js
function getComponent () {
return import('lodash').then(_ => {
console.log(_.join(['a', 'b'], '##'))
})
}
getComponent()

// webpack.config.js
module.exports = {
mode: 'production',
devtool: 'cheap-module-eval-source-map',
entry: {
index1: './index.js'
},
plugins: [new HtmlWebpackPlugin({
template: './index.html'
}), new CleanWebpackPlugin()
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'sef')
}
}

Prefetching

目的

第三方依赖包进行代码分离,虽然第二次可以从缓存中获取。但对第一次加载却加载多个js文件,影响效率。
所以splitChunks的chunks默认是async,webpack建议我们按需加载。
Preloading/Prefetching: 在网络带宽空闲的时候将按其他资源加载好。

演示代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 同步加载
// index.js
document.addEventListener('click', function () {
let div = document.createElement('div')
div.innerText = 'Ethan'
document.querySelector('.app').append(div)
})

// 按需加载
// index.js
document.addEventListener('click', function () {
import('./index1.js').then(({ default: fn }) => {
fn()
})
})
// index1.js
function fn () {
let div = document.createElement('div')
div.innerText = 'Ethan'
document.querySelector('.app').append(div)
}
export default fn
查看代码的使用率
1
浏览器:ctrl+shift+p ---> show Coverage ---> 左上方圆圈点击为红色 ---> 刷新页面 ---> 查看使用率
Prefetching配置
1
2
3
4
5
6
// index.js
document.addEventListener('click', function () {
import(/*webpackPrefetch: true*/'./index1.js').then(({ default: fn }) => {
fn()
})
})

css分离

目的

将css样式从html文件中分离

MiniCssExtractPlugin配置

不支持热更新,所以只要配置生产环境。同时将webpack.common.js的css规则移到development配置下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
npm install --save-dev mini-css-extract-plugin
npm i -D optimize-css-assets-webpack-plugin
npm i -D terser-webpack-plugin

// webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const commonConfig = require('./webpack.common.js')
const merge = require('webpack-merge')
const path = require('path')

const prodConfig = {
mode: 'production',
devtool: 'cheap-module-eval-source-map',
plugins: [
new MiniCssExtractPlugin()
],
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
},
module: {
rules: [{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'postcss-loader',
'sass-loader'
]
}, {
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'
]
}]
},
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
path: path.resolve(__dirname, 'dist')
}
}

module.exports = merge(commonConfig, prodConfig)


// index.js
import './style.css'

// style.css
body{
background: red;
}