# 多页网站 WebPack5
配置
# 准备工作
基本安装
mkdir MultiPageWeb cd MultiPageWeb npm init -y npm install webpack webpack-cli -S
1
2
3
4将页面结构 (opens new window)放到
src
文件夹中目录结构
配置
webpack.config.js
module.exports = { entry: {}, module: {}, plugins: [], output: { clean: true, } }
1
2
3
4
5
6
7
8配置
package.json
{ "name": "melon", "version": "1.0.0", "description": "多页面网站Webpack配置", - "main": "index.js", + "private": true, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "dev": "webpack --mode=development", + "build": "webpack --mode=production" }, "author": "Melon", "license": "ISC", }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 项目使用 webpack
的优化
webpack
是一个模块打包器 将任意资源文件 转换、打包或包裹 用于浏览器中使用
# html
资源处理
安装
htmlWebpackPlugin
(opens new window) 识别html
文件+ const htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: {}, module: {}, plugins: [ + new htmlWebpackPlugin({ + template: "./src/html/index.html", + filename: "index.html", + }), + new htmlWebpackPlugin({ + template: "./src/html/login.html", + filename: "login.html", + }), ], output: { clean: true, } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19运行
npm run dev
后dist
文件夹会生成html
文件安装
html-loader
(opens new window) 可以识别html
文件里面的资源module: { + rules: [ + { + test: /\.html$/i, + loader: "html-loader", + }, + ], }
1
2
3
4
5
6
7
8运行
npm run dev
后dist
文件夹生成对应的静态资源
# SCSS
资源处理
安装
sass-loader
(opens new window) 和css-loader
(opens new window) 处理样式文件- 页面也不再直接引入
css
样式文件 - 改为从
webpack.config.js
中引入scss
样式文件
const htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { + index: ["./src/scss/index.scss"], + login: ["./src/scss/login.scss"] }, module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, + { + test: /\.(sc|sa|c)ss$/i, + use: [ + 'css-loader', + 'sass-loader', + ], + }, ], }, plugins: [ new htmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", }), new htmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", }), ], output: { clean: true, } }
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- 页面也不再直接引入
运行
npm run dev
后 思考几个问题dist
文件夹里面的html
文件的head
引入变化- 自动生成
css
样式文件 可是要怎么使用
使用
style-loader
(opens new window) 将生成的样式文件作用到html
文件中dist
文件夹里面的css
样式文件合并到页面对应的js
文件中
{ test: /\.(sc|sa|c)ss$/i, use: [ + 'style-loader', 'css-loader', 'sass-loader', ], },
1
2
3
4
5
6
7
8使用
MiniCssExtractPlugin
(opens new window) 会将CSS
提取到单独的文件dist
文件夹里面会生成对应的css
样式文件- 生成的
html
会自动引入样式文件 ⚠️观察引入的个数
const htmlWebpackPlugin = require('html-webpack-plugin'); + const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { entry: { index: ["./src/scss/index.scss"], login: ["./src/scss/login.scss"] }, module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, { test: /\.(sc|sa|c)ss$/i, use: [ - 'style-loader', + MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], }, ], }, plugins: [ new htmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", }), new htmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", }), + new MiniCssExtractPlugin() ], output: { clean: true, } }
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由于现在是多入口文件 导致生成的每一个页面都会包含入口文件的内容 所以需要 指定页面的对应资源
plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", + chunks: ['index'] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", + chunks: ['login'] }), new MiniCssExtractPlugin() ],
1
2
3
4
5
6
7
8
9
10
11
12
13
# JavaScript
资源处理
页面的脚本文件也在入口文件统一引入 而不需要在页面直接引入
entry: { - index: ["./src/scss/index.scss"], + index: ["./src/scss/index.scss", "./src/js/index.js"], - login: ["./src/scss/login.scss"] + login: ["./src/scss/login.scss", "./src/js/login.js"] },
1
2
3
4
5
6
# 图片资源处理
使用 htmlWebpackPlugin
会自动将图片资源文件移动到 dist
文件夹下 但是并没有对于图片有任何的优化处理
在
webpack4
时会使用url-loader
(opens new window) 将小图片转base64
从而减少网络请求- 图片尺寸小于
20480B = 20KB
时 会自动将图片转成base64
scss
文件引入的图片则会生成二进制图片 无法直接读取
module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, { test: /\.(sc|sa|c)ss$/i, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], }, + { + test: /\.(png|jpg|gif)$/, + use: { + loader: 'url-loader', + options: { + name: '[name].[ext]', + limit: 20480, + outputPath: 'images', + }, + } + } ], },
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- 图片尺寸小于
在
webpack5
时 新增 资源模块 (opens new window) 进行静态资源的处理- 自动根据图片尺寸使用不同
loader
进行处理
module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, { test: /\.(sc|sa|c)ss$/i, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], }, + { + test: /\.(png|jpg|gif)$/, + type: 'asset', + parser: { + dataUrlCondition: { + maxSize: 20 * 1024 + } + }, + generator: { + filename: 'images/[name][ext]' + } + }, - { - test: /\.(png|jpg|gif)$/, - use: { - loader: 'url-loader', - options: { - name: '[name].[ext]', - limit: 20480, - outputPath: 'images', - }, - } - } ], },
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- 自动根据图片尺寸使用不同
-
- 使用
imagemin-jpegtran
(opens new window) 对于jpg
格式图片进行无损压缩 - 使用
imagemin-optipng
(opens new window) 对于png
格式图片进行无损压缩
const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); + const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", chunks: ['index'] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", chunks: ['login'] }), new MiniCssExtractPlugin(), + new ImageMinimizerPlugin({ + minimizerOptions: { + plugins: [ + ["jpegtran", { progressive: true }], + ["optipng", { optimizationLevel: 5 }], + ], + }, + }) ]
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运行
npm run build
观察压缩结果⚠️ 安装上面两个包时一定要用 国外
npm
源 不要用淘宝源或者cnpm
源 否则会出现 下面的错误安装后 运行
npm audit fix
修复包的依赖才可以正常使用
- 使用
-
根据文档
webpack5
是内置了squooshMinify
插件来压缩图片 可是 ⚠️minify
属性不支持 不知道为什么使用
imagemin-mozjpeg
(opens new window) 对于jpg
格式图片进行有损压缩使用
imagemin-pngquant
(opens new window) 对于png
格式图片进行有损压缩
plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", chunks: ['index'] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", chunks: ['login'] }), new MiniCssExtractPlugin(), - new ImageMinimizerPlugin({ - minimizerOptions: { - plugins: [ - ["jpegtran", { progressive: true }], - ["optipng", { optimizationLevel: 5 }], - ], - }, - }), + new ImageMinimizerPlugin({ + minimizerOptions: { + plugins: [ + ["mozjpeg", { quality: 75 }], + ["pngquant"] + ], + }, + }), ],
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运行
npm run build
观察压缩结果⚠️ 安装上面两个包时一定要用 国外
npm
源 不要用淘宝源或者cnpm
源 否则会出现 下面的错误安装后 运行
npm audit fix
修复包的依赖才可以正常使用
图片换成
webp
格式- 使用
imagemin-webp
(opens new window) 自动将png
格式图片生成为webp
格式 - 在
src
的index.html
引入f2.png
- 小尺寸
png
图片要转成base64
不需要转webp
格式
plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", chunks: ['index'] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", chunks: ['login'] }), new MiniCssExtractPlugin(), - new ImageMinimizerPlugin({ - minimizerOptions: { - plugins: [ - ["mozjpeg", { quality: 75 }], - ["pngquant"] - ], - }, - }), + new ImageMinimizerPlugin({ + test: /\.(jpe?g)$/i, + minimizerOptions: { + plugins: [["mozjpeg", { quality: 75 }]], + }, + }), + new ImageMinimizerPlugin({ + test: /\.(png)$/i, + minimizerOptions: { + plugins: ["pngquant"], + }, + }), + new ImageMinimizerPlugin({ + test: /\.(png)$/i, + deleteOriginalAssets: false, + filename: "images/[hash].webp", + filter: source => { + return source.byteLength > 20480 + }, + minimizerOptions: { + plugins: ["imagemin-webp"], + }, + }) ]
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运行
npm run build
观察转化结果
- 使用
将图片上传到
CDN
使用
melon-cos-plugin
(opens new window) 将图片上传到腾讯云自动将
html
和css
里面引入的图片png
类型变为webp
类型const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); + const MelonCosPlugin = require("melon-cos-plugin"); + const projectName = "multipageweb"; + const dirName = new Date().toLocaleDateString(); module.exports = { plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", chunks: ['index'] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", chunks: ['login'] }), new MiniCssExtractPlugin(), new ImageMinimizerPlugin({ test: /\.(jpe?g)$/i, minimizerOptions: { plugins: [["mozjpeg", { quality: 75 }]], }, }), new ImageMinimizerPlugin({ test: /\.(png)$/i, minimizerOptions: { plugins: ["pngquant"], }, }), new ImageMinimizerPlugin({ test: /\.(png)$/i, deleteOriginalAssets: false, filename: "images/[hash].webp", filter: source => { return source.byteLength > 20480 }, minimizerOptions: { plugins: ["imagemin-webp"], }, }), + new MelonCosPlugin({ + projectName, + dirName, + SecretId: 'COS账号', + SecretKey: 'COS密码', + Bucket: '存储桶ID', + Region: '存储桶地区' + }) ], output: { clean: true, + publicPath: `https://cos.0melon0.cn/${projectName}/${dirName}/` } }
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
# 完整版配置文件(区分环境开发)
项目环境配置
package.json
{ "name": "multi-page-web-webpack", "version": "1.0.0", "description": "", "private": true, "scripts": { "dev": "webpack --config=webpack.dev.js", "start": "webpack serve --open --config=webpack.dev.js", "build": "webpack --name=melon --config=webpack.prod.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "cos-nodejs-sdk-v5": "^2.10.5", "css-loader": "^6.4.0", "fontmin-webpack": "^3.1.0", "html-loader": "^2.1.2", "html-webpack-plugin": "^5.4.0", "image-minimizer-webpack-plugin": "^2.2.0", "imagemin-mozjpeg": "^9.0.0", "imagemin-pngquant": "^9.0.2", "imagemin-webp": "^6.0.0", "melon-cos-plugin": "^1.0.4", "melon-min-font-plugin": "^1.0.5", "mini-css-extract-plugin": "^2.4.2", "sass": "^1.43.2", "sass-loader": "^12.2.0", "style-loader": "^3.3.0", "webpack": "^5.58.2", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.3.1", "webpack-sources": "^3.2.1" } }
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页面配置文件
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { index: ['./src/scss/index.scss', './src/js/index.js'], login: ['./src/scss/login.scss', './src/js/login.js'] }, plugins: [ new HtmlWebpackPlugin({ template: "./src/html/index.html", filename: "index.html", chunks: ["index"] }), new HtmlWebpackPlugin({ template: "./src/html/login.html", filename: "login.html", chunks: ["login"] }), ] }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20开发环境配置
webpack.dev.js
const BaseConfig = require("./webpack.config"); module.exports = { entry: BaseConfig.entry, module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, { test: /\.(sc|sa|c)ss$/i, use: [ "style-loader", 'css-loader', 'sass-loader', ], }, { test: /\.(png|jpg|gif)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 20 * 1024 } }, generator: { filename: 'images/[name][ext]' } }, ], }, plugins: BaseConfig.plugins, devServer: { static: './dist', watchFiles: ['./src/**/*'], proxy: { context: "/api", changeOrigin: true, }, }, devtool: 'inline-source-map', mode: "development", output: { clean: true, }, stats: { children: true, errorDetails: true } }
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上线配置
webpack.prod.js
const BaseConfig = require("./webpack.config"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); const MelonCosPlugin = require("melon-cos-plugin"); const MelonMinFontPlugin = require("melon-min-font-plugin"); module.exports = (env, argv) => { try { let projectName = argv.name || 'temp'; let dirName = new Date().toLocaleDateString().replace(/\//g, ""); return { entry: BaseConfig.entry, module: { rules: [ { test: /\.html$/i, loader: "html-loader", }, { test: /\.(sc|sa|c)ss$/i, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', generator: { filename: 'fonts/[name][ext]' } }, { test: /\.(png|jpg|gif)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 20 * 1024 } }, generator: { filename: 'images/[name][ext]' } }, ], }, plugins: [ ...BaseConfig.plugins, new MiniCssExtractPlugin(), new ImageMinimizerPlugin({ test: /\.(jpe?g)$/i, minimizerOptions: { plugins: [["mozjpeg", { quality: 75 }]], }, }), new ImageMinimizerPlugin({ test: /\.(png)$/i, minimizerOptions: { plugins: ["pngquant"], }, }), new ImageMinimizerPlugin({ test: /\.(png)$/i, filename: "images/[name].webp", filter: source => { return source.byteLength > 20480 }, minimizerOptions: { plugins: ["imagemin-webp"], }, }), new MelonMinFontPlugin({ exclude: ['iconfont.ttf'] }), new MelonCosPlugin({ projectName, dirName, SecretId: '账号', SecretKey: '密钥', Bucket: '存储桶', Region: '地区' }) ], mode: "production", output: { clean: true, publicPath: `https://cos域名/${projectName}/${dirName}/` } } } catch (error) { console.log("全局try捕获"); console.log(error); } }
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
# 疑惑点
图片上传到
COS
后 前端页面可以判断是否支持Webp
格式 但是 不支持的情况下如何请求回原来的图片格式呢?(function (doc) { if (!sessionStorage.getItem(isWebp)) { let image = new Image(); image.onload = function () { if (image.width == 1) { sessionStorage.setItem(isWebp, true); } else { // 不支持Webp格式时的处理 } }; image.src = 'data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA=='; } }(document));
1
2
3
4
5
6
7
8
9
10
11
12
13使用
image-minimizer-webpack-plugin
可以将html
和scss
里面引入的图片压缩、转换Webp
格式 可是 在不同文件中引入同一张图片时 会重复处理图片资源导致Multiple assets emit different content to the same filename
错误因为
HTTP
的限制 最多支持六个并发请求 我们现在除了页面外 其他一切资源上传到COS
所以如何设置多域名来解决域名并发上限