七、生产环境 优化构建速度
1. OneOf
作用:让每个规则只匹配一个文件,大大增加构建速度
module里面的rules里,每个规则都会扫一遍全部的文件,这样会大大增加构建的速度,
而加了OneOf,就可以让每个规则只匹配一个文件,大大增加构建速度,但不能有两个配置处理同一种类型文件,如js
//webpack.config.js文件
module: {
rules: [
{
test: /\.js$/, //js语法检查
exclude: /node_modules/,
enforce: 'pre', // 优先执行
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: '60',
firefox: '50'
}
}
]
]
}
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
})
//...
],
// 生产环境
mode: 'production'
}
2. 缓存
作用:如果已经构建过了且没有变化,则直接读取缓存,如果有变化,则构建后读取
对babel进行换缓存 只需要在loader: ‘babel-loader’, 加一行cacheDirectory: true就可以实现babel缓存
对文件资源进行缓存
当别人访问你的服务时,css、js资源会被强制缓存下来,当下次访问时,不会重新加载资源,而是直接读缓存,
而决定走缓存还是重新加载资源,是根据资源名字是否改变决定的比如a.js 内容为1,index.html引入a.js, 第一次会加载资源,第二次会走缓存,而此时你把a.js内容改为1、2,
index.html引入a.js,则别人再次访问时,还是会读取内容为1的js,因为a.js名称没变,会一直读取原来的缓存
Webpack中有3种hash值
hash: 每次webpack构建时会生成一个唯一的hash值。
chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样,可以打到改变那个文件,那个文件的文件名改变的效果
使用hash或chunkhash时,如果只改变了css,则会导致css和js都会重新生成一个新的hash值,就会导致改变1个文件,而多个文件同时变化的问题
而contenthash则是根据内容是否改变来决定是否生产新的hash值,不会出现改变css文件,而相关联文件也发生变化的情况,所以对文件资源进行缓存用contenthash
//webpack.config.js文件
module: {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js', //输出的文件名改为contenthash
path: resolve(__dirname, 'build'),
},
rules: [
{
test: /\.js$/, //js语法检查
exclude: /node_modules/,
enforce: 'pre', // 优先执行
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 以下loader只会匹配一个
// 注意:不能有两个配置处理同一种类型文件
oneOf: [
../
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: '60',
firefox: '50'
}
}
]
],
// 开启babel缓存
// 第二次构建时,会读取之前的缓存,速度更快
cacheDirectory: true
}
}
]
}
]
},
3. 多进程打包
多进程打包:某个任务消耗时间较长会卡顿,多进程可以同一时间干多件事,效率更高。
优点是提升打包速度,缺点是每个进程的开启和交流都会有开销(babel-loader消耗时间最久,所以使用thread-loader针对其进行优化)
建议项目比较大,或者工作消耗时间比较长,才需要多进程打包
安装命令:npm install thread-loader -d
//webpack.config.js文件
module.exports = {
//...
module: {
rules: [
{
test: /\.js$/, //js的兼容性处理
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {
version: 3
},
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
],
// 开启babel缓存第二次构建时,会读取之前的缓存
cacheDirectory: true
}
//...
],
},
plugins: [
//...
],
}
4. dll 动态链接库
dll动态链接库,可以对某些库(第三方库jquery、react、vue…)进行单独打包
作用:只需要一开始对第三方库打包一次,后面再打包时,只需要打包源代码,不再对第三方库打包了,这样编译会快很多需要新增一个 webpack.dll.js文件
//webpack.dll.js文件
/*
使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
当你运行 webpack 时,默认查找 webpack.config.js 配置文件
需求:需要运行 webpack.dll.js 文件
--> webpack --config webpack.dll.js
*/
const { resolve } = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
// 最终打包生成的[name] --> jquery
// ['jquery'] --> 要打包的库是jquery
jquery: ['jquery'],
},
output: {
filename: '[name].js',
path: resolve(__dirname, 'dll'),
library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
},
plugins: [
// 打包生成一个 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name: '[name]_[hash]', // 映射库的暴露的内容名称
path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
})
],
mode: 'production'
};
//webpack.config.js文件
//...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
// 告诉webpack哪些库不参与打包,同时使用时的名称也得变~
new webpack.DllReferencePlugin({
manifest: resolve(__dirname, 'dll/manifest.json')
}),
// 将某个文件打包输出去,并在html中自动引入该资源
new AddAssetHtmlWebpackPlugin({
filepath: resolve(__dirname, 'dll/jquery.js')
})
],