优化
# 公共路径 publicPath
publicPath 配置公共路径,所有文件的引用将自动添加公共路径的绝对地址。
module.exports = {
...
output: {
...
publicPath: 'https://localhost:3000/'
}
}
2
3
4
5
6
7
# 环境变量 Environment variable
环境变量可以消除 webpack.config.js 在开发环境和生产环境之间的差异
module.exports = ( env ) => {
return {
...
mode: env.production ? 'production' : 'development'
}
}
2
3
4
5
6
7
打包命令时如果使用生产模式,则在命令后增加:
npx webpack --env production
# 配置文件优化
分别对 development
和 production
两种模式优化。完整配置文件可查看本页下方 “完整配置”。
- 1、首先新建 webpack-config 文件夹,在文件夹中添加三个文件,分别为通用的配置文件、开发模式的配置文件以及生产模式的配置文件。
- 2、使用 webpack-merge 将文件进行合并。安装 webpack-merge
npm i webpack-merge -D
- 3、添加一个合并文件 webpack.config.js
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.config.common");
const developmentConfig = require("./webpack.config.dev");
const productionConfig = require("./webpack.config.prod");
module.exports = (env) => {
switch (true) {
case env.development:
return merge(commonConfig, developmentConfig);
case env.production:
return merge(commonConfig, productionConfig);
default:
return new Error("No matching configuration was found.");
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 4、修改 package.json 文件
// 将自定义的命令分别指向相应的文件以及添加 env 环境变量的参数
{
"scripts": {
"start": "webpack serve -c ./webpack-config/webpack.config.js --env development",
"build": "webpack -c ./webpack-config/webpack.config.js --env production"
},
}
2
3
4
5
6
7
- 5、使用命令运行
npm run start
npm run build
2
# HMR ( 开发环境 )
Hot module replacement 热模块替换,可使一个模块发生变化,只重新打包这一个模块,而非全部重新打包,可以更快速的构建代码打包速度。
module.exports = {
...
devServer: {
...
// 开启 HMR 功能
hot: true
}
}
2
3
4
5
6
7
8
- 视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=60
- 视频教程:https://www.bilibili.com/video/BV1e7411j7T5?p=20
# Source Map
一种提供源代码到构建后代码映射的技术,如果构建后代码出错了,通过映射关系可以追踪源代码的错误。在 webpack.config.js 文件中配置
module.exports = {
...
devtool: 'source-map'
}
2
3
4
常用的几种 source-map 类型
- source-map:生成外部文件,错误代码的准确信息和源代码的错误位置
- inline-source-map:内联,错误代码的准确信息和源代码的错误位置。在代码底部生成,构建速度比外部文件更快
- hidden-source-map:生成外部文件,错误代码的原因,没有错误位置,无法追踪源代码错误。
- eval-source-map:内联,错误代码的准确信息和源代码的错误位置。每一个文件都生成对应的 source-map
- nosources-source-map:生成外部文件,
- cheap-source-map:生成外部文件,错误代码的准确信息和源代码的错误位置。只精确到行
- cheap-module-source-map:同 cheap-source-map,会将 loader 的 source map 加入 开发环境建议
- eval-source-map
- eval-cheap-module-source-map 生产环境建议
- source-map
- nosources-source-map
- hidden-source-map 视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=58
# Oneof ( 生产模式 )
每个 loader 只会匹配一个,不能有两个配置处理一个类型的文件 https://www.bilibili.com/video/BV1e7411j7T5?p=22
module.exports = {
module: {
rules: [
{
oneOf: [
{
// 处理 css 资源
test: /\.css$/i,
use: [...CommonCssLoader],
},
{
// 处理 scss 资源
test: /\.s[ac]ss$/i,
use: [...CommonCssLoader, "sass-loader"],
},
{
// 处理图片资源
test: /\.(jpg|jpeg|png|gif)$/i,
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[hash:12].[ext]",
esModule: false,
outputPath: "images",
},
},
{
// 处理 html 中的图片资源
test: /\.html$/i,
loader: "html-loader",
},
],
},
],
},
};
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
# Tree shaking ( 生产模式 )
去除应用程序中没有使用的代码,可更大程度的优化代码。必须使用 ES6 模块化,并开启 production 模式。
import { module } from './filename.js'
如果不需要某些文件被 webpack 清除,可以在 package.json 中配置 sideEffects 属性
{
"sideEffects": ["*.css" ,"*.scss", "*.global.js"...]
}
2
3
# Code split ( 生产模式 )
代码分离是 webpack 中最引人瞩目的特性之一,可将代码分离到不同的文件中,然后将这些文件按需加载或并行加载,同时还可以获取代码加载的优先级。
# 方法 1: 入口起点( 不推荐 )
使用 entry 配置手动分离代码,如果多个入口共享的文件,会分别在每个包里重复打包。
module.exports = {
entry: {
main: "./assets/js/main.js",
other: "./assets/js/add.js",
},
output: {
filename: "js/[name].bundle.js",
path: path.resolve(__dirname, "dist"),
},
};
2
3
4
5
6
7
8
9
10
# 方法 2: 防止重复
使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离代码
module.exports = {
entry: {
main: {
import: "./assets/js/main.js",
dependOn: "shared",
},
other: {
import: "./assets/js/add.js",
dependOn: "shared",
},
shared: "jQuery",
},
output: {
filename: "js/[name].bundle.js",
path: path.resolve(__dirname, "dist"),
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# sliptChunks 插件
另外,还可使用 sliptChunks 插件来实现
module.exports = {
...
entry: {
main: './assets/js/main.js',
other: './assets/js/add.js'
},
output: {
filename: 'js/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
optimization: {
sliptChunks: {
chunks: 'all'
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可以通过 import 方法对文件名进行自定义
import(/* webpackChunkName: '自定义文件名' */'文件路径')
# 方法 3: 动态导入
function getComponent() {
import("lodash").then(({ default: _ }) => {
const element = document.createElement("div");
element.innerHTML = _.join(["Hello", "webpack", ""]);
return element;
});
}
getComponent().then((element) => {
document.body.appendChild(element);
});
2
3
4
5
6
7
8
9
10
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=40
# 懒加载
指的是 JS 文件的懒加载,当事件触发或条件满足后才进行加载。是很好的优化网页或应用的方法。这种方法实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用一些新的代码块。这样加快了应用的初始加载速度,减轻总体体积,因为某些代码块可能永远不会被加载。
document.querySelector('button').addEventListener('click', () => {
import(/* webpackChunkName: 'filename' */'./filename').then(({ module }) => {
...
})
})
2
3
4
5
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=44 视频教程:https://www.bilibili.com/video/BV1e7411j7T5?p=26
# 预加载
等其他资源加载完毕后再进行加载,当事件触发或条件满足后,才会执行。兼容性较差,只能在 pc 端高版本浏览器中使用,手机端浏览器兼容较差。
document.querySelector('button').addEventListener('click', () => {
import(/* webpackChunkName: 'filename', webpackPrefetch: true */'./filename').then(({ module }) => {
...
})
})
2
3
4
5
# 缓存 ( 生产模式 )
使用 hash 值为文件命名。
module.exports = {
...
output: {
filename: 'js/[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
}
2
3
4
5
6
7
# 缓存第三方库
将第三方库提取到单独的 vendor chunk 文件中。利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。
module.exports = {
...
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=47 视频教程:https://www.bilibili.com/video/BV1e7411j7T5?p=23
# PWA
https://www.bilibili.com/video/BV1e7411j7T5?p=27 渐进式网络应用开发程序,可实现网页离线访问,兼容性较差 下载插件
npm i workbox-webpack-plugin -D
配置
// 引入插件
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
// 配置
module.exports = {
...
plugins: [
new WorkboxWebpackPlugin.GenerateSW({
// 帮组 serviceworkder 快速启动
clientsClaim: true,
// 删除旧的 serviceworker
skipWaiting: true
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// js 文件中注册
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceworker.register("/service-worker.js");
});
}
2
3
4
5
6
会和 eslint 产生冲突,需要修改 package.json 中 eslintConfig 配置 必须运行在服务器上
# 多进程打包
通常给 babel 使用,只有工作消耗时间较长时才建议使用。 下载
npm i thread-loader -D
# Externals
为了减小打包后的文件体积,从而把一些第三方库用 cdn 的形式引入进来,如 jQuery。Externals 就是用来防止将某些文件打包到最终生成的文件包中。 定义外部第三方包
module.exports = {
...
// 定义标签类型
externalsType: 'script',
// 定义第三方包
externals: {
jquery: [
'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js',
'jQuery'
]
}
}
2
3
4
5
6
7
8
9
10
11
12
在 JS 文件中使用 import 方式引入,这里 from 后的名称需和定义时的名称进行对应。
import $ from 'jQuery'
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=65
# Shimming
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=78
# Export
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=80
# Dll
https://www.bilibili.com/video/BV1e7411j7T5?p=30 动态连接库,dll 会对某些库(第三方)进行单独打包。 1、下载好第三方库后,使用 import 语法在 JS 文件中引入文件
import { gsap } from 'gsap';
2、在根目录中创建 webpack.dll.js
const path = require("path");
const Webpack = require("webpack");
module.exports = {
entry: {
// 需要单独打包的库
gsap: ["gsap"],
},
output: {
// 输出文件名称
filename: "[name].js",
// 输出文件路径
path: path.resolve(__dirname, "../dll"),
// 导出库名称
library: "[name]",
},
plugins: [
// 引入插件
new Webpack.DllPlugin({
// 对应导出的库名称
name: "[name]",
// 生成 manifest 文件
path: path.resolve(__dirname, "../dll/manifest.json"),
}),
],
mode: "production",
};
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
3、在 package.json 中编辑
"scripts": {
"dll": "webpack --config ./webpack.dll.js"
}
2
3
4、执行指令
npm run dll
5、然后配置 webpack.config.js 文件
const path = require('path')
const Webpack = require('webpack')
module.exports = {
...
plugins: [
// 告诉 webpack 哪些库布参与打包,以及使用的名称
new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dll/manifest.json')
})
]
}
2
3
4
5
6
7
8
9
10
11
12
6、如需在页面中自动引用,需安装一个插件 add-asset-html-webpack-plugin,再在 webpack.config.js 文件中进行配置
npm i add-asset-html-webpack-plugin -D
const path = require('path')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports = {
...
plugins: [
// 在html中自动引入
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, 'dll/gsap.js'),
publicPath: './'
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=70 视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=90
# 依赖图 Dependency graph
每当一个文件依赖另一个文件时,webpack 会直接将文件视为存在依赖关系。这使 webpack 可以获取非代码资源,如 images 或 web 字体等。并会把他们作为依赖提供给应用程序。当 webpack 开始工作时,它会根据我们写好的配置,从入口 (Entry) 开始,webpack 会递归的构建一个依赖关系图,这个依赖图包含着应用程序中所需的每个模块,然后将所有模块打包为输出文件。 bundle 分析工具 webpack-chart:webpack stats 可交互饼图; webpack-visualizer:可视化并分析你的 bundle,检查哪些模块占用空间,哪些可能使重复使用的; webpack-bundle-analyzer:一个 plugin 和 CLI 工具,它将 bundle 内容展示为一个便捷的、交互式、可缩放的树状图形式; webpack bundle optimize helper:分析你的 bundle 并提供可操作的改进措施,减少 bundle 的大小; bundle-stats:生成一个 bundle 报告 ( bundle 大小、资源、模块 ),并比较不同构建之间的结果。 视频教程:https://www.bilibili.com/video/BV1YU4y1g745?p=66
评论
- 表情