项目中配置 webpack 有三个目的,打包速度,打包体积,运行流畅度,速度指的是run build
的时间,体积是指dist
的大小,流畅指的是打开页面是否不卡顿
打包速度
提升打包速度有以下方式,范围优化,多进程打包,利用缓存
测试打包速度利用speed-measure-webpack-plugin
如:
js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
plugins: [
new VueLoaderPlugin(),
new SpeedMeasurePlugin(),
new HtmlWebpackPlugin({ template: "./public/index.html" }), //JS或者CSS文件可以自动引入到html中
],
范围优化
alias 配置路径别名,优化文件查找速度
javascript
function pathResolve(dir) {
return path.join(__dirname,dir)
}
resolve: {
alias: {
"@": pathResolve("src"),
"page":pathResolve("src/page")
},
},
extensions 文件扩展名配置,频率高的放在前面
javascript
resolve: {
extensions: [".js", ".css", ".vue"], //第一种配置后缀名
extensions: [".vue", ".js", ".json", ".css"], //第二种配置后缀名
},
modules 解析模块时应该搜索的目录
javascript
resolve: {
// modules: ["node_modules", pathResolve("src")],
},
javascript
resolve: {
modules: ["node_modules", pathResolve("src")],
},
externals 配置
配合 cdn 降低一些依赖打包构建
- 不配置externals
安装 jquery
shell
npm install jquery
javascript
<template>
<router-view></router-view>
</template>
<script>
import $ from 'jquery'
import { cloneDeep } from "lodash";
export default {
name: "App",
mounted() {
const aa = {
ddd: () => {
console.log(1111);
},
};
console.log(cloneDeep(aa));
console.log($('.app'))
},
};
</script>
<style scoped></style>
- 配置 externals
javascript
externals: {
jquery: 'jQuery',
},
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
noParse
防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中 不应该含有 <font style="color:rgb(43, 58, 66);">import</font>
, <font style="color:rgb(43, 58, 66);">require</font>
, <font style="color:rgb(43, 58, 66);">define</font>
的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。
javascript
module.exports = {
//...
module: {
noParse: /jquery|lodash/,
},
};
include/exclude
控制范围提高构建速度
**<font style="color:rgb(251, 112, 53);background-color:rgb(238, 238, 238);">include</font>**
:符合条件的模块进行解析**<font style="color:rgb(251, 112, 53);background-color:rgb(238, 238, 238);">exclude</font>**
:排除符合条件的模块,不解析,优先级更高
javascript
{ test: /\.js$/, exclude: /node_modules/,include: pathResolve('src'), loader: "babel-loader" },
IgnorePlugin
阻止为与正则表达式或过滤器函数匹配的 <font style="color:rgb(43, 58, 66);">import</font>
或 <font style="color:rgb(43, 58, 66);">require</font>
调用生成模块;
可以用于 momentjs 处理时区
多进程打包
thread-loader 使用时,需将此 loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
每个 worker 都是一个独立的 node.js 进程,其开销大约为 600ms 左右。同时会限制跨进程的数据交换。
请仅在耗时的操作中使用此 loader!
缓存
js 缓存
javascript
{
test: /\.js$/,
exclude: /node_modules/,
include: pathResolve("src"),
use: [
{
loader: "babel-loader", // 开启多进程打包
options: {
cacheDirectory: true,
},
},
],
},
样式缓存
添加 cache-loader
javascript
{
test: /\.less$/,
use: [
"style-loader",
"cache-loader",
"css-loader",
"less-loader",
],
},
持久化缓存
webpack5 开启 cache 缓存模块
javascript
module.exports = {
//...
cache: {
type: 'memory',
},
};
打包体积
测试打包体积利用<font style="color:#DF2A3F;">webpack-bundle-analyzer</font>
,打包时会开启本地构建每个包的大小
javascript
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
module.exports = {
plugins: [
new VueLoaderPlugin(),
// new SpeedMeasurePlugin(),
new BundleAnalyzerPlugin(),
new HtmlWebpackPlugin({ template: "./public/index.html" }), //JS或者CSS文件可以自动引入到html中
],
}
CSS 压缩
powershell
npm install css-minimizer-webpack-plugin --save-dev
javascript
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimize: true, // 开启后会在开发环境生效
minimizer: [
// 添加 css 压缩配置
new CssMinimizerPlugin(),
],
},Ï
}
JS 压缩
webpack5 内置了terser-webpack-plugin插件,所以我们不需重复安装,直接引用就可以了,具体配置如下
powershell
module.exports = {
optimization: {
minimize: true, // 开发环境开启才生效
minimizer: [
new TerserPlugin({})
]
},
}
TREE SHAKING 摇树
打包时不将项目中引入未使用的代码打包进去,在 package.json 中开启 sideEffects
powershell
{
sideEffects:false/true/[]
}
- true 所有文件都有副作用,全都不可
<font style="background-color:rgb(238, 238, 238);">tree-shaking</font>
- false 有这些文件有副作用,所有其他文件都可以
<font style="background-color:rgb(238, 238, 238);">tree-shaking</font>
,但会保留这些文件 - [] 选中的单位进行
<font style="color:rgb(85, 85, 85);">tree shaking</font>
GZIP 压缩
在构建过程中生成Gzip文件,从而减少传输到客户端的数据大小,提高加载速度。
powershell
npm install compression-webpack-plugin --save-dev
javascript
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = {
// 其他配置...
plugins: [
new CompressionWebpackPlugin({
filename: '[path][base].gz', // 输出的Gzip文件名格式
algorithm: 'gzip', // 使用gzip算法
test: /\.js$|\.css$|\.html$/, // 哪些文件需要进行压缩
threshold: 10240, // 只有文件大小大于该值时才会被压缩,默认是10KB
minRatio: 0.8, // 压缩率小于这个值的资源将不会被压缩
deleteOriginalAssets: false // 是否删除原文件,默认为false
})
],
};
运行流畅度
运行流畅度优化的目的就是提升首屏的加载速度,方式有降低首屏加载文件体积,首屏不需要的文件进行预加载或者按需加载
splitChunks 分包
首屏分包利用浏览器的并发请求来提高首屏包的加载速度,<font style="color:rgb(44, 44, 54);">splitChunks</font>
允许我们将公共模块、第三方库等拆分到单独的 chunk 文件中,从而实现更细粒度的代码分割和缓存策略。
javascript
module.exports = {
// 其他配置...
optimization: {
splitChunks: {
chunks: 'all', // 对所有类型的chunk进行处理(包括异步和非异步)
minSize: 20000, // 形成一个新chunk最小的文件大小(单位:字节)
maxSize: 0, // 最大尺寸目标,超过该值会尝试再分割,默认为0表示不启用
minChunks: 1, // 模块至少应被共享的次数(即最少引用了多少次)
maxAsyncRequests: 30, // 按需加载的最大并行请求数
maxInitialRequests: 30, // 入口点处的最大并行请求数
automaticNameDelimiter: '~', // 文件名连接符
name(module, chunks, cacheGroupKey) {
return cacheGroupKey + '_' + chunks.map(chunk => chunk.name).join('~');
}, // 自定义chunk名称生成规则
cacheGroups: { // 缓存组配置
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配node_modules下的模块
priority: -10, // 优先级,数值越大优先级越高
filename: 'vendors.js', // 输出文件名
enforce: true, // 强制分割,即使未达到minSize条件也进行分割
},
default: {
minChunks: 2, // 模块至少被引用两次才会被提取
priority: -20,
reuseExistingChunk: true, // 如果当前chunk包含已从主bundle中拆分出的模块,则重用而不是创建新的chunk
},
},
},
},
};
图片懒加载
利用 prefetch 和 preload 来优化大图片加载过慢问题
- prefetch (预获取):浏览器空闲的时候进行资源的拉取
- preload (预加载):提前加载后面会用到的关键资源
javascript
import( /* webpackPrefetch: true */ './img')
import(/* webpackPreload: true */ './img');
总结
webpack 优化的三个目的速度,体积,流畅度在很多大项目中都是十分必要的,不管后续如何优化都万变不离其宗