定义

  1. 本质上,webpack是一个用于现代JavaScript应用程序的静态模块打包工具。当webpack处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个bundles,它们均为静态资源,用于展示你的内容。
  2. 静态模块:指的是编写代码过程中的html,css,js,图片等固定内容的文件
  3. 打包:把静态模块内容,压缩,整合,转译等(前端工程化)
  • 把less/sass 转成 css代码
  • 把ES6+降级成 ES5
  • 支持多种模块标准语法(例如:CommonJs、ECMAScript)

使用

  1. 在终端中输入命令为当前开发环境配置webpack
1
npm i webpack webpack-cli --save-dev
  1. 在package.json文件中编写自定义命令
1
2
3
"scripts": {
"build": "webpack"
},
  1. 运行打包命令,自动产生dist分发文件夹(压缩和优化后,用于最终运行的代码)
1
npm run build

修改Webpack打包的出口和入口

  1. 在项目根目录下,新建 webpack.config.js 配置文件
  2. 导出配置对象,配置入口,出口文件的路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const path = require('path')

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
}
}

自动生成html文件

  1. 下载 html-webpack-plugin 本地软件包
1
npm i html-webpack-plugin --save-dev
  1. 配置 webpack.config.js 让 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
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
})
]
}

打包 CSS 代码

加载器 css-loader:解析 css 代码

加载器 style-loader:把解析后的 css 代码插入到 DOM

  1. 在js文件中引入css文件代码
1
import css from "file.css"
  1. 下载 css-loader 和 style-loader 本地软件包
1
npm i css-loader style-loader --save-dev
  1. 配置 webpack.config.js 让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
25
26
27
28
29
30
31
32
33
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
}
}

优化-提取 CSS 代码

插件:mini-css-extract-plugin:提取 css 代码

  1. 下载 mini-css-extract-plugin 本地软件包
1
npm install --save-dev mini-css-extract-plugin
  1. 配置 webpack.config.js 让 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象,可以传入相对路径,相对于output.path目录
new MiniCssExtractPlugin({
filename: './login/index.css'
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
],
}
}

注意mini-css-extract-plugin插件和style-loader不能一起使用

mini-css-extract-plugin插件是提取css代码,并生成css文件

优化-压缩 CSS 代码

  1. 下载 css-minimizer-webpack-plugin 本地软件包
1
npm install css-minimizer-webpack-plugin --save-dev
  1. 配置 webpack.config.js 让 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
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
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象
new MiniCssExtractPlugin()
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
],
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}

打包 less 代码

加载器 less-loader:把 less 代码编译为 css 代码

  1. 将less代码文件引入js文件中
1
import "my.less"
  1. 下载 less 和 less-loader 本地软件包
1
npm i less less-loader --save-dev
  1. 配置 webpack.config.js 让 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
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
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象
new MiniCssExtractPlugin()
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /\.less$/i,
// use: ["style-loader", "css-loader", "less-loader"],
// Webpack 的 loader 执行顺序是 从右到左 或 从下到上。所以应该先执行less-loader
// 后执行css-loader,最后再提取css代码到独立文件中
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
}
],
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}

打包图片

资源模块:Webpack5 内置资源模块(字体、图片等)打包,无需额外 loader

配置webpack.config.js 让 Webpack 拥有打包图片功能

  • 占位符 【hash】对模块内容做算法计算,得到映射的数字字母组合的字符串
  • 占位符【ext】使用当前模块原本的占位符,例如 :. png/.jpg等字符串
  • 占位符【query】保留引入文件时代码中查询参数(只有URL下生效)
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
60
61
62
63
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象
new MiniCssExtractPlugin()
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /\.less$/i,
// use: ["style-loader", "css-loader", "less-loader"],
// Webpack 的 loader 执行顺序是 从右到左 或 从下到上。所以应该先执行less-loader
// 后执行css-loader,最后再提取css代码到独立文件中
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
],
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}

注意:

  1. 判断临界值默认为8kb
  • 大于8kb 文件:生成一个单独的文件并导出URL地址
  • 小于8kb 文件:导出一个data URI(base64字符串)
  1. js 中引入本地图片资源要用 import 方法(如果是网络图片http地址,可以直接将http地址赋值给src属性),否则无法对图片进行打包

搭建开发环境

开发环境:配置webpack-dev-server 快速开发应用程序

作用:启动 Web 服务,自动检测代码变化,热更新到网页

注意:dist 目录和打包内容是在内存里(更新快)

  1. 下载 webpack-dev-server 软件包到当前项目
1
npm i webpack-dev-server --save-dev
  1. 设置模式为开发模式,并配置自定义命令
  • 在webpack.config.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
// 打包模式(development 开发模式-使用相关内置优化)
mode: 'development',
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象
new MiniCssExtractPlugin()
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
{
test: /\.less$/i,
// use: ["style-loader", "css-loader", "less-loader"],
// Webpack 的 loader 执行顺序是 从右到左 或 从下到上。所以应该先执行less-loader
// 后执行css-loader,最后再提取css代码到独立文件中
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
],
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}
  • 在package.json文件中配置
1
2
3
4
5
"scripts": {
"build": "webpack",
// 自定义命令,--open意思是每次热更新后都会打开浏览器,不需要可以删去
"dev": "webpack serve --open"
},
  1. 使用 npm run dev 来启动开发服务器,实现热更新效果
1
npm run dev

注意1:webpack-dev-server 借助 http 模块创建 8080 默认 Web 服务

注意2:默认访问public下的index.html文件

注意3:webpack-dev-server 根据配置,打包相关代码在内存当中,以 output.path 的值作为服务器根目录(所以可以直接自己拼接访问 dist 目录下内容,此dist目录存在于内存中,并非项目中的dist目录)

打包模式

打包模式:告知 Webpack 使用相应模式的内置优化

  1. 分类:
模式名字 模式名字 特点 场景
开发模式 development 调试代码,实时加载,模块热替换等 本地开发
生产模式 production 压缩代码,资源优化,更轻量等 打包上线
  1. 设置
  • 方式一:在 webpack.config.js 配置文件设置 mode 选项
1
2
3
4
5
6
// ...

module.exports = {
// ....
mode: 'production'
}
  • 方式二:在 package.json 命令行设置 mode 参数
1
2
3
4
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack serve --mode=development"
},

命令行设置优先级高于配置文件中的设置

打包模式的应用

根据不同的环境采用不同的打包模式

  1. 方案一:webpcak.config.js 配置导出函数,但是局限性大(只接受两种模式)
  2. 方案二:借助 cross-env(跨平台通用)包命令,设置参数区分环境
  • 下载 cross-env 软件包到当前项目
1
npm i cross-env --save-dev
  • 配置自定义命令,传入参数和值(会绑定到 process.env 对象下)
1
2
3
4
"scripts": {
"build": "cross-env NODE_ENV=production webpack --mode=production",
"dev": "cross-env NODE_ENV=development webpack serve --mode=development"
},
  • 在 webpcak.config.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

module.exports = {
// 打包模式(development 开发模式-使用相关内置优化)
mode: 'development',
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 注册HtmlWebpackPlugin对象
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/index.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html')
}),
// 注册MiniCssExtractPlugin对象
new MiniCssExtractPlugin()
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
},
{
test: /\.less$/i,
// use: ["style-loader", "css-loader", "less-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
],
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}
  1. 方案三:配置不同 webpcak.config.js (适用多种模式差异性较大的情况)

webpack 官网:https://webpack.docschina.org/

前端 - 注入环境变量

问题:cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV

解决:适用 webpack 内置的 DefinePlugin 插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ....
const webpack = require('source/_posts/frontend/Webpack')

module.exports = {
// ...
plugins: [
// ...
new webpack.DefinePulgin({
// key 是注入到打包后的前端JS代码中作为全局变量
// value 是变量对应的值(在cross-env注入在node.js中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
}
1
2
3
4
5
// 示例
if (process.env.NODE_ENV === 'production') {
console.log = function () {}
}
console.log('生产环境不执行打印语句,开发环境执行')

开发环境调错 - source map

问题:代码被压缩和混淆,无法正确定位源代码位置(行数和列数)

source map:可以准确追踪 error 和 warning 在原始代码的位置

设置:webpack.config.js 配置 devtool选项

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

config = {
mode: 'development',
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/login.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/login.html')
}),
new MiniCssExtractPlugin({
filename: './login/index.css'
}),
new webpack.DefinePlugin({
// key 是注入到打包后的前端JS代码中作为全局变量
// value 是变量对应的值(在cross-env注入在node.js中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
},
{
test: /\.less$/i,
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
}
}

if (process.env.NODE_ENV === 'development') {
config.devtool = 'inline-source-map'
}

module.exports = config

inline-source-map 选项:把源码的位置信息一起打包在js文件内

注意:source map 仅适用于开发环境,不要再生产环境使用(防止被轻易查看源码位置)

解析别名 alias

解析别名:配置模块如何解析,创建 import 引入路径别名,来确保模块引入变得更简单

在webpack.config.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

config = {
mode: 'development',
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/login.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/login.html')
}),
new MiniCssExtractPlugin({
filename: './login/index.css'
}),
new webpack.DefinePlugin({
// key 是注入到打包后的前端JS代码中作为全局变量
// value 是变量对应的值(在cross-env注入在node.js中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
},
{
test: /\.less$/i,
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
},
// 配置解析
resolve: {
// 配置解析别名
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}

if (process.env.NODE_ENV === 'production') {
config.devtool = 'inline-source-map'
}

module.exports = config
1
2
3
// webpack 会默认给文件添加js/json后缀,所以文件如果是js/json格式可不加后缀
import youAxios from '@/utils/request'
console.log(youAxios)

优化 - CDN使用

CDN 定义

CDN定义:内容分发网络,指的是一组分布在各个地区的服务器

作用:把静态资源文件/第三方库放在CDN网络中各个服务器中,供用户就近请求获取

好处:减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略

webpack 使用 CDN

为减小上线后前端代码的体积,可以在开发模式下使用本地第三方库,生产模式下使用 CDN 加载引入第三方库

  1. 在html文件中引入在cdn服务器上的第三方库,并用模板代码包裹
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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 模板语法,useCdn为false,则不引入,为true,则引入 -->
<% if (htmlWebpackPlugin.options.useCdn){ %>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.7/css/bootstrap.min.css" rel="stylesheet">
<% } %>
<title>黑马头条-数据管理平台</title>
</head>

<body>
<!-- 警告框 -->
<div class="alert info-box">
操作结果
</div>
<!-- 登录页面 -->
<div class="login-wrap">
<div class="title">黑马头条</div>
<div>
<form class="login-form">
<div class="item">
<input type="text" class="form-control" name="mobile" placeholder="请输入手机号" value="13888888888">
</div>
<div class="item">
<input type="text" class="form-control" name="code" placeholder="默认验证码246810" value="246810">
</div>
<div class="item">
<button type="button" class="btn btn-primary btn">登 录</button>
</div>
</form>
</div>
</div>
<!-- 模板语法,useCdn为false,则不引入,为true,则引入 -->
<% if (htmlWebpackPlugin.options.useCdn){ %>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.11.0/axios.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.7/js/bootstrap.min.js"></script>
<% } %>
</body>

</html>

免费的cdn服务器:https://www.bootcdn.cn/

免费的cdn服务器:https://unpkg.com/

第二个服务器需要在网址后面加第三方包名,按下enter即可自动跳转到对应的cdn地址

  1. 在webpack.config.js文件中配置useCdn属性
  2. 在webpack.config.js文件中配置 externals(外部扩展)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

config = {
mode: 'development',
// 配置入口文件
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件
filename: './login/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/login.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/login.html'),
// 自定义属性,在html模板中 <% if (htmlWebpackPlugin.option.useCdn){ %> 访问使用
// 如果是开发环境,则useCdn为false,否则为true
useCdn: process.env.NODE_ENV === 'production'
}),
new MiniCssExtractPlugin({
filename: './login/index.css'
}),
new webpack.DefinePlugin({
// key 是注入到打包后的前端JS代码中作为全局变量
// value 是变量对应的值(在cross-env注入在node.js中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
},
{
test: /\.less$/i,
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
},
// 配置解析
resolve: {
// 配置解析别名
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}

// 开发环境中,将源码的位置信息一起打包在js文件内
if (process.env.NODE_ENV === 'development') {
config.devtool = 'inline-source-map'
}

// 生成环境中,
if (process.env.NODE_ENV === 'production') {
config.externals = {
// key:代码中import from 后面的模块标识字符串
// value:留在原地的变量名(要和 cdn 暴露在全局的变量名一致)
/* 这段代码是 Webpack 配置中的 externals(外部扩展)配置,
用于告诉 Webpack 哪些模块不需要打包到最终的 dist 中,而是通过外部方式引入 */
'axios': 'axios', // cdn暴露的axios变量名就是axios
"bootstrap/dist/css/bootstrap.min.css": 'bootstrap' // cdn暴露的bootstrap变量名就是bootstrap
}
}

module.exports = config

打包多页面

查找使用 npm 下载第三方库的命令官网:https://www.npmjs.com/

在webpack.config.js中配置多入口和多页面的设置即可实现打包多个html文件(多页面)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ...
const config = {
entry: {
'模块名1':path.resolve(_dirname,'src/入口1.js'),
'模块名2':path.resolve(_dirname,'src/入口2.js'),
},
output: {
path: path.resolve(_dirname, 'dist'),
filename: './[name]/index.js'
}
plugins: [
new HtmlWebpackPlugin({
template:'./public/页面1.html',//模板文件
filename:'./路径/index.html',//输出文件
chunks : ['模块名1']
}),
new HtmlWebpackPlugin({
template:'./public/页面2.html',//模板文件
filename:'./路径/index.html',//输出文件
chunks : ['模块名2']
})
]
}
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")

config = {
mode: 'development',
// 配置输入路径
// entry: path.resolve(__dirname, 'src/login/index.js'),
entry: {
// 配置入口1:login
'login': path.resolve(__dirname, 'src/login/index.js'),
// 配置入口2:content
'content': path.resolve(__dirname, 'src/content/index.js'),
// 配置入口3:publish
'publish': path.resolve(__dirname, 'src/publish/index.js')
},
// 配置输出路径
output: {
// 配置出口文件路径
path: path.resolve(__dirname, 'dist'),
// 配置出口文件,[name]占位,与上述配置的入口key值有关
filename: './[name]/index.js',
// 在打包生成内容之前清空输出路径中的目录文件
clean: true
},
// 配置插件(给webpack提供更多功能)
plugins: [
// 配置输出登录页面的html文件,HtmlWebpackPlugin 不支持基于入口名的动态模板路径,所以不能用[name]占位符区分content页面和login页面
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/login.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/login/index.html'),
// 自定义属性,在html模板中 <% if (htmlWebpackPlugin.option.useCdn){ %> 访问使用
// 如果是开发环境,则useCdn为false,否则为true
useCdn: process.env.NODE_ENV === 'production',
chunks: ['login'] // 关键:只注入 login 入口的资源
}),
// 配置输出内容页面的html文件
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/content.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/content/index.html'),
// 自定义属性,在html模板中 <% if (htmlWebpackPlugin.option.useCdn){ %> 访问使用
// 如果是开发环境,则useCdn为false,否则为true
useCdn: process.env.NODE_ENV === 'production',
chunks: ['content'] // 关键:只注入 content 入口的资源
}),
// 配置输出发布页面的html文件
new HtmlWebpackPlugin({
// 配置模板文件
template: path.resolve(__dirname, 'pubLic/publish.html'),
// 配置输出文件
filename: path.resolve(__dirname, 'dist/publish/index.html'),
// 自定义属性,在html模板中 <% if (htmlWebpackPlugin.option.useCdn){ %> 访问使用
// 如果是开发环境,则useCdn为false,否则为true
useCdn: process.env.NODE_ENV === 'production',
chunks: ['publish'] // 关键:只注入 content 入口的资源
}),
// 配置提取的css文件路径,[name]占位,与上述配置的入口key值有关
new MiniCssExtractPlugin({
filename: './[name]/index.css'
}),
new webpack.DefinePlugin({
// key 是注入到打包后的前端JS代码中作为全局变量
// value 是变量对应的值(在cross-env注入在node.js中的环境变量字符串)
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
// 加载器(让webpack识别更多模块文件)
module: {
rules: [
{
test: /\.css$/i,
// use: ["style-loader", "css-loader"],
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader"]
},
{
test: /\.less$/i,
// 如果环境变量为production,则启动抽离css代码的形式打包css代码,否则采用嵌入到dom形式打包css代码
use: [process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader', "css-loader", "less-loader"]
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
generator: {
filename: 'assets/[hash][ext][query]'
}
}
]
},
// 优化
optimization: {
// 最小化
minimizer: [
// 在 webpack@5 中,你可以使用 ` ... ` 语法来扩展现有的minimizer(即使用内置的
//`terser-webpack-plugin`插件进行扩展,即可实现对JS代码进行压缩 ),将下一行取消注释,就可以保证 JS代码还能被压缩处理
`...`,
new CssMinimizerPlugin(),
],
},
// 配置解析
resolve: {
// 配置解析别名
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}

// 开发环境中,将源码的位置信息一起打包在js文件内
if (process.env.NODE_ENV === 'development') {
config.devtool = 'inline-source-map'
}

// 生成环境中,
if (process.env.NODE_ENV === 'production') {
config.externals = {
// key:代码中import from 后面的模块标识字符串
// value:替换在原地的变量名(要和 cdn 暴露在全局的变量名一致)
/* 这段代码是 Webpack 配置中的 externals(外部扩展)配置,
用于告诉 Webpack 哪些模块不需要打包到最终的 dist 中,而是通过外部方式引入 */
'axios': 'axios', // cdn暴露的axios变量名就是axios
"bootstrap/dist/css/bootstrap.min.css": 'bootstrap', // cdn暴露的bootstrap变量名就是bootstrap
'form-serialize': 'serialize', // cdn暴露的form-serialize变量名就是serialize
'@wangeditor/editor': 'WangEditor' // cdn暴露的wangeditor变量名就是WangEditor
}
}

module.exports = config

优化 - 分割公共代码

配置webpack.config.js的splitChunks 分隔功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ...
const config = {
// ...
optimization: {
splitChunks: {
chunks:'all', //所有模块动态非动态移入的都分割分析
cacheGroups:{ // 分隔组
commons:{ // 抽取公共模块
minSize:0, //抽取的chunk最小大小字节
minChunks:2, //最小引用数
reuseExistingChunk: true, //当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用
name(module, chunks, cacheGroupKey){ //分离出模块文件名
const allChunksNames =chunks.map((item)=> item.name).join('~') //模块名1~模块名2
return`./js/${allChunksNames}` //输出到 dist 目录下位置
}
}
}
}
}
}