前言
各位读者好,我正在努力学习前端中,这里是尚硅谷2022版Webpack5入门到原理文档资料分享,我会在其中添加一些我的认为的重点,希望能够对大家有用。
我学习的视频链接是尚硅谷2022版Webpack5
此外,我还有其它前端内容的笔记,大家有需要的可以自行查找。
由于文件内容太大,打开跳转反应慢,我将其分为四篇方便大家阅读使用,下面是链接
基础
高级
项目
原理
文章目录
基础
webpack基本认识
开发时,我们会使用框架(React、Vue),ES6 模块化语法,Less/Sass 等 css 预处理器等语法进行开发。
这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、Css 等语法,才能运行。
所以我们需要打包工具帮我们做完这些事。
除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等。
有哪些打包工具?
- Grunt
- Gulp
- Parcel
- Webpack
- Rollup
- Vite
- …
目前市面上最流量的是 Webpack,所以我们主要以 Webpack 来介绍使用打包工具
Webpack
是一个静态资源打包工具。
它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
输出的文件就是编译好的文件,就可以在浏览器段运行了。
我们将 Webpack
输出的文件叫做 bundle
。
功能介绍
Webpack 本身功能是有限的:
- 开发模式:仅能编译 JS 中的
ES Module
语法 - 生产模式:能编译 JS 中的
ES Module
语法,还能压缩 JS 代码
开始使用
1. 资源目录
webpack_code # 项目根目录(所有指令必须在这个目录运行)
└── src # 项目源码目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目主文件
2. 创建文件
- count.js
//返回两数之差
export default function count(x, y) {
return x - y;
}
- sum.js
//reduce是累加器方法,是为了计算数组内元素之和
export default function sum(...args) {
return args.reduce((p, c) => p + c, 0);
}
- main.js
import count from "./js/count";
import sum from "./js/sum";
console.log(count(2, 1));//输出为 1
console.log(sum(1, 2, 3, 4));//输出为10
3. 下载依赖
打开终端,来到项目根目录。运行以下指令:
- 初始化
package.json
npm init -y
此时会生成一个基础的 package.json
文件。
注意:我们会在这里对数量众多的包进行统计与管理
需要注意的是 package.json
中 name
字段不能叫做 webpack
, 否则下一步会报错
- 下载依赖
注意:webpack 与webpack-cli是一个绑定的存在,每回使用两个必须同时下载,webpack 是打包工具,webpack-cli 是 webpack 的命令行接口。
npm i webpack webpack-cli -D
4. 启用 Webpack
- 开发模式
npx webpack ./src/main.js --mode=development
- 生产模式
npx webpack ./src/main.js --mode=production
npx webpack
: 是用来运行本地安装 Webpack
包的。
./src/main.js
: 指定 Webpack
从 main.js
文件开始打包,不但会打包 main.js
,还会将其依赖也一起打包进来。
--mode=xxx
:指定模式(环境)。
5. 观察输出文件
默认 Webpack
会将文件打包输出到 dist
目录下,我们查看 dist
目录下文件情况就好了
小结
Webpack
本身功能比较少,只能处理 js
资源,一旦遇到 css
等其他资源就会报错。
所以我们学习 Webpack
,就是主要学习如何处理其他资源。
注意:在下方我们会得到几种处理css资源的方法,每次完成项目选择一种适合的即可
基本配置
在开始使用 Webpack
之前,我们需要对 Webpack
的配置有一定的认识。
5 大核心概念
- entry(入口)
指示 Webpack 从哪个文件开始打包
- output(输出)
指示 Webpack 打包完的文件输出到哪里去,如何命名等
- loader(加载器)
webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析
- plugins(插件)
扩展 Webpack 的功能
- mode(模式)
主要由两种模式:
- 开发模式:development
- 生产模式:production
准备和修改配置文件
在项目根目录下新建文件:webpack.config.js
Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范
注意:关于node.js的path模块可以参考一下,我一个笔记,简单了解即可,在webpack中使用并不复杂。
node.js中的path模块
- 配置文件
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
module.exports = {
// 入口***********************************************************
// 相对路径和绝对路径都行
entry: "./src/main.js",
// 输出
output: {
// path: 文件输出目录,必须是绝对路径
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, "dist"),
// filename: 输出文件名
filename: "main.js",
},
// 加载器************************************************************
module: {
rules: [],
},
// 插件*************************************************************
plugins: [],
// 模式*************************************************************
mode: "development", // 开发模式
};
- 运行指令
npx webpack
此时功能和之前一样,也不能处理样式资源
小结
Webpack 将来都通过 webpack.config.js
文件进行配置,来增强 Webpack 的功能
我们后面会以两个模式来分别搭建 Webpack 的配置,先进行开发模式,再完成生产模式
开发模式介绍
开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
- 编译代码,使浏览器能识别运行
开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
- 代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。
提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
处理样式资源
本章节我们学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源
介绍
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用
官方文档找不到的话,可以从社区 Github 中搜索查询
注意:建议保持官方文档地址,学会阅读官方文档,会使你时刻把握行业最前沿的技术信息
处理 Css 资源
1. 下载包
npm i css-loader style-loader -D
注意:需要下载两个 loader
2. 功能介绍
css-loader
:负责将 Css 文件编译成 Webpack 能识别的模块style-loader
:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
此时样式就会以 Style 标签的形式在页面上生效
3. 配置
const path = require("path");
module.exports = {
//入口路径*********************************************************
entry: "./src/main.js",
//出口路径**********************************************************
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
//模块的控制********************************************************
module: {
//控制规则
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
],
},
plugins: [],
mode: "development",
};
4. 添加 Css 资源
- src/css/index.css
.box1 {
width: 100px;
height: 100px;
background-color: pink;
}
- src/main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入 Css 资源,Webpack才会对其打包
import "./css/index.css";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
- public/index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<!-- 准备一个使用样式的 DOM 容器 -->
<div class="box1"></div>
<!-- 引入打包后的js文件,才能看到效果 -->
<script src="../dist/main.js"></script>
</body>
</html>
5. 运行指令
npx webpack
打开 index.html 页面查看效果
注意:这里是前文中导入css文件打包失败的结果对比,经此操作,可以成功打包css文件
处理 Less 资源
1. 下载包
npm i less-loader -D
2. 功能介绍
less-loader
:负责将 Less 文件编译成 Css 文件
3. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
plugins: [],
mode: "development",
};
4. 添加 Less 资源
- src/less/index.less
.box2 {
width: 100px;
height: 100px;
background-color: deeppink;
}
- src/main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/index.css";
import "./less/index.less";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
- public/index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<div class="box1"></div>
<div class="box2"></div>
<script src="../dist/main.js"></script>
</body>
</html>
5. 运行指令
npx webpack
打开 index.html 页面查看效果
注意:这里是前文中导入less文件打包失败的结果对比,经此操作,可以成功打包less文件
处理 Sass 和 Scss 资源
1. 下载包
npm i sass-loader sass -D
注意:需要下载两个
2. 功能介绍
sass-loader
:负责将 Sass 文件编译成 css 文件sass
:sass-loader
依赖sass
进行编译
3. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
plugins: [],
mode: "development",
};
4. 添加 Sass 资源
- src/sass/index.sass
/* 可以省略大括号和分号 */
.box3
width: 100px
height: 100px
background-color: hotpink
- src/sass/index.scss
.box4 {
width: 100px;
height: 100px;
background-color: lightpink;
}
- src/main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
- public/index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<script src="../dist/main.js"></script>
</body>
</html>
5. 运行指令
npx webpack
打开 index.html 页面查看效果
注意:道理同上
处理 Styl 资源
1. 下载包
npm i stylus-loader -D
2. 功能介绍
stylus-loader
:负责将 Styl 文件编译成 Css 文件
3. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
],
},
plugins: [],
mode: "development",
};
4. 添加 Styl 资源
- src/styl/index.styl
/* 可以省略大括号、分号、冒号 */
.box
width 100px
height 100px
background-color pink
- src/main.js
import { add } from "./math";
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
- public/index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<!-- 准备一个使用样式的 DOM 容器 -->
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
<script src="../dist/main.js"></script>
</body>
</html>
5. 运行指令
npx webpack
打开 index.html 页面查看效果
处理图片资源
过去在 Webpack4 时,我们处理图片资源通过 file-loader
和 url-loader
进行处理
注意:file-loader的功能是将图片编译成为webpack能识别的语言,而url-loader 将这些图片通过 base64的方式引入代码中。这样就节省了请求次数,从而提高页面性能
现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源
1. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
/*对于type: asset,webpack 将按照默认条件,自动地在 resource 和
inline 之间进行选择:小于 8kb 的文件,将会视为 inline 模块类型,
否则会被视为 resource 模块类型
asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file
-loader 实现。
asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之
前通过使用 url-loader,并且配置资源体积限制实现。*/
type: "asset",
},
],
},
plugins: [],
mode: "development",
};
2. 添加图片资源
图片资源是自己设置的,这里是我们提前准备的图片资源
- src/images/1.jpeg
- src/images/2.png
- src/images/3.gif
3. 使用图片资源
- src/less/index.less
.box2 {
width: 100px;
height: 100px;
background-image: url("../images/1.jpeg");
background-size: cover;
}
- src/sass/index.sass
.box3
width: 100px
height: 100px
background-image: url("../images/2.png")
background-size: cover
- src/styl/index.styl
.box5
width 100px
height 100px
background-image url("../images/3.gif")
background-size cover
4. 运行指令
npx webpack
打开 index.html 页面查看效果
5. 输出资源情况
此时如果查看 dist 目录的话,会发现多了三张图片资源
因为 Webpack 会将所有打包好的资源输出到 dist 目录下
- 为什么样式资源没有呢?
因为经过 style-loader
的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来
6. 对图片资源进行优化
将小于某个大小的图片转化成 data URI 形式(Base64 格式)
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
//依据图片大小控制图片的打包方式
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
}
}
},
],
},
plugins: [],
mode: "development",
};
- 优点:减少请求数量
- 缺点:体积变得更大
此时输出的图片文件就只有两张,有一张图片以 data URI 形式内置到 js 中了
(注意:需要将上次打包生成的文件清空,再重新打包才有效果)
修改输出资源的名称和路径
1. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
/*
在访问一个网站的时候,可能会见到网址中有这样一段 ?id=1 或者
他类似 ?xxx=xxx 格式,这部分在定义上叫做 query(有问号的意思,
很形象了),也被称为 URL 访问参数(URL parameter)或者直接叫做
URL 参数。以 ?id=1 为例,? 表示参数的开始, id 就是参数名,
=1 表示参数的值为 1 。如果有多个参数的话,使用 & 来分隔参数。
*/
filename: "static/imgs/[hash:8][ext][query]",
},
},
],
},
plugins: [],
mode: "development",
};
2. 修改 index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
<!-- 修改 js 资源路径 -->
<script src="../dist/static/js/main.js"></script>
</body>
</html>
3. 运行指令
npx webpack
- 此时输出文件目录:
(注意:需要将上次打包生成的文件清空,再重新打包才有效果)
├── dist
└── static
├── imgs
│ └── 7003350e.png
└── js
└── main.js
自动清空上次打包资源
1. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js",
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 40 * 1024, // 小于40kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
],
},
plugins: [],
mode: "development",
};
2. 运行指令
npx webpack
观察 dist 目录资源情况
处理字体图标资源
1. 下载字体图标文件
-
选择想要的图标添加到购物车,统一下载到本地
2. 添加字体图标资源
-
src/fonts/iconfont.ttf
-
src/fonts/iconfont.woff
-
src/fonts/iconfont.woff2
-
src/css/iconfont.css
- 注意字体文件路径需要修改
-
src/main.js
import { add } from "./math";
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/iconfont.css";//字体图标资源的引用
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";
console.log(count(2, 1));
console.log(sum(1, 2, 3, 4));
- public/index.html
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
<!-- 使用字体图标 -->
<i class="iconfont icon-arrow-down"></i>
<i class="iconfont icon-ashbin"></i>
<i class="iconfont icon-browse"></i>
<script src="../dist/static/js/main.js"></script>
</body>
</html>
3. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
],
},
plugins: [],
mode: "development",
};
type: "asset/resource"
和type: "asset"
的区别:
type: "asset/resource"
相当于file-loader
, 将文件转化成 Webpack 能识别的资源,其他不做处理type: "asset"
相当于url-loader
, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式
注意:大小是8k
4. 运行指令
npx webpack
打开 index.html 页面查看效果
处理其它资源
开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
注意:就是在处理字体图标资源基础上增加其他文件类型,统一处理即可
1. 配置
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?|map4|map3|avi)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
],
},
plugins: [],
mode: "development",
};
2. 运行指令
npx webpack
打开 index.html 页面查看效果
处理 js 资源
由于 Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理。
其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。
- 针对 js 兼容性处理,我们使用 Babel 来完成
- 针对代码格式,我们使用 Eslint 来完成
我们先完成 Eslint,检测代码格式无误后,在由 Babel 做代码兼容性处理
Eslint
可组装的 JavaScript 和 JSX 检查工具。它是用来检测 js 和 jsx 语法的工具,可以配置各项功能
我们使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查
1. 配置文件
配置文件由很多种写法:
.eslintrc.*
:新建文件,位于项目根目录.eslintrc
.eslintrc.js
.eslintrc.json
- 区别在于配置格式不一样
package.json
中eslintConfig
:不需要创建文件,在原有文件基础上写
ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
2. 具体配置
我们以 .eslintrc.js
配置文件为例:
module.exports = {
// 解析选项
parserOptions: {},
// 具体检查规则
rules: {},
// 继承其他规则
extends: [],
};
其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
- parserOptions 解析选项
parserOptions: {
ecmaVersion: 6, // ES 语法版本
sourceType: "module", // ES 模块化
ecmaFeatures: { // ES 其他特性
jsx: true // 如果是 React 项目,就需要开启 jsx 语法
}
}
- rules 具体规则
"off"
或0
- 关闭规则"warn"
或1
- 开启规则,使用警告级别的错误:warn
(不会导致程序退出)"error"
或2
- 开启规则,使用错误级别的错误:error
(当被触发的时候,程序会退出)
rules: {
semi: "error", // 禁止使用分号
'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
'default-case': [
'warn', // 要求 switch 语句中有 default 分支,否则警告
{ commentPattern: '^no default$' } // 允许在最后注释 no default, 就不会有警告了
],
eqeqeq: [
'warn', // 强制使用 === 和 !==,否则警告
'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
],
}
更多规则详见:规则文档
- extends 继承
开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。
现有以下较为有名的规则:
- Eslint 官方的规则:
eslint:recommended
- Vue Cli 官方的规则:
plugin:vue/essential
- React Cli 官方的规则:
react-app
// 例如在React项目中,我们可以这样写配置
module.exports = {
extends: ["react-app"],
rules: {
// 我们的规则会覆盖掉react-app的规则
// 所以想要修改规则直接改就是了
eqeqeq: ["warn", "smart"],
},
};
3. 在 Webpack 中使用
- 下载包
npm i eslint-webpack-plugin eslint -D
- 定义 Eslint 配置文件
- .eslintrc.js
module.exports = {
// 继承 Eslint 规则
extends: ["eslint:recommended"],
env: {
node: true, // 启用node中全局变量
browser: true, // 启用浏览器中全局变量
},
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
rules: {
"no-var": 2, // 不能使用 var 定义变量
},
};
- 修改 js 文件代码
- main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/iconfont.css";
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";
var result1 = count(2, 1);
console.log(result1);
var result2 = sum(1, 2, 3, 4);
console.log(result2);
注意:这里的结果应当是扔出错误
- 配置
- webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
mode: "development",
};
- 运行指令
npx webpack
在控制台查看 Eslint 检查效果
4. VSCode Eslint 插件
打开 VSCode,下载 Eslint 插件,即可不用编译就能看到错误,可以提前解决
但是此时就会对项目所有文件默认进行 Eslint 检查了,我们 dist 目录下的打包后文件就会报错。但是我们只需要检查 src 下面的文件,不需要检查 dist 下面的文件。
所以可以使用 Eslint 忽略文件解决。在项目根目录新建下面文件:
.eslintignore
# 忽略dist目录下所有文件
dist
Babel
JavaScript 编译器。
主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
1. 配置文件
配置文件由很多种写法:
babel.config.*
:新建文件,位于项目根目录babel.config.js
babel.config.json
.babelrc.*
:新建文件,位于项目根目录.babelrc
.babelrc.js
.babelrc.json
package.json
中babel
:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可
2. 具体配置
我们以 babel.config.js
配置文件为例:
module.exports = {
// 预设
presets: [],
};
- presets 预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env
: 一个智能预设,允许您使用最新的 JavaScript。@babel/preset-react
:一个用来编译 React jsx 语法的预设@babel/preset-typescript
:一个用来编译 TypeScript 语法的预设
3. 在 Webpack 中使用
- 下载包
npm i babel-loader @babel/core @babel/preset-env -D
- 定义 Babel 配置文件
- babel.config.js
module.exports = {
presets: ["@babel/preset-env"],
};
- 修改 js 文件代码
- main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/iconfont.css";
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";
const result1 = count(2, 1);
console.log(result1);
const result2 = sum(1, 2, 3, 4);
console.log(result2);
- 配置
- webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
mode: "development",
};
- 运行指令
npx webpack
打开打包后的 dist/static/js/main.js
文件查看,会发现箭头函数等 ES6 语法已经转换了
处理 Html 资源
1. 下载包
npm i html-webpack-plugin -D
2. 配置
- webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "public/index.html"),
}),
],
mode: "development",
};
3. 修改 index.html
去掉引入的 js 文件,因为 HtmlWebpackPlugin 会自动引入
<!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" />
<title>webpack5</title>
</head>
<body>
<h1>Hello Webpack5</h1>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
<i class="iconfont icon-arrow-down"></i>
<i class="iconfont icon-ashbin"></i>
<i class="iconfont icon-browse"></i>
</body>
</html>
4. 运行指令
npx webpack
此时 dist 目录就会输出一个 index.html 文件
开发服务器&自动化
每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化
1. 下载包
npm i webpack-dev-server -D
2. 配置
- webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true, // 自动将上次打包目录资源清空
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "public/index.html"),
}),
],
// 开发服务器
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
mode: "development",
};
3. 运行指令
npx webpack serve
注意运行指令发生了变化
并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
开发时我们只关心代码能运行,有效果即可,至于代码被编译成什么样子,我们并不需要知道。
生产模式介绍
生产模式是开发完成代码后,我们需要得到代码将来部署上线。
这个模式下我们主要对代码进行优化,让其运行性能更好。
优化主要从两个角度出发:
- 优化代码运行性能
- 优化代码打包速度
生产模式准备
我们分别准备两个配置文件来放不同的配置
1. 文件目录
├── webpack-test (项目根目录)
├── config (Webpack配置文件目录)
│ ├── webpack.dev.js(开发模式配置文件)
│ └── webpack.prod.js(生产模式配置文件)
├── node_modules (下载包存放目录)
├── src (项目源码目录,除了html其他都在src里面)
│ └── 略
├── public (项目html文件)
│ └── index.html
├── .eslintrc.js(Eslint配置文件)
├── babel.config.js(Babel配置文件)
└── package.json (包的依赖管理配置文件)
2. 修改 webpack.dev.js
因为文件目录变了,所以所有绝对路径需要回退一层目录才能找到对应的文件
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: undefined, // 开发模式没有输出,不需要指定输出目录
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
// clean: true, // 开发模式没有输出,不需要清空输出结果
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// 其他省略
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
mode: "development",
};
运行开发模式的指令:
npx webpack serve --config ./config/webpack.dev.js
3. 修改 webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
运行生产模式的指令:
npx webpack --config ./config/webpack.prod.js
4. 配置运行指令
为了方便运行不同模式的指令,我们将指令定义在 package.json 中 scripts 里面
// package.json
{
// 其他省略
"scripts": {
"start": "npm run dev",
"dev": "npx webpack serve --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"
}
}
以后启动指令:
- 开发模式:
npm start
或npm run dev
- 生产模式:
npm run build
Css 处理
提取 Css 成单独文件
Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
我们应该是单独的 Css 文件,通过 link 标签加载性能才好
1. 下载包
npm i mini-css-extract-plugin -D
2. 配置
- webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//新增导入模块
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
3. 运行指令
npm run build
Css 兼容性处理
1. 下载包
npm i postcss-loader postcss postcss-preset-env -D
2. 配置
- webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"less-loader",
],
},
{
test: /\.s[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"sass-loader",
],
},
{
test: /\.styl$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"stylus-loader",
],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
3. 控制兼容性
我们可以在 package.json
文件中添加 browserslist
来控制样式的兼容性做到什么程度。
{
// 其他省略
"browserslist": ["ie >= 8"]
}
想要知道更多的 browserslist
配置,查看browserslist 文档
以上为了测试兼容性所以设置兼容浏览器 ie8 以上。
实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:
{
// 其他省略
"browserslist": ["last 2 version", "> 1%", "not dead"]
}
注意:浏览器的版本限制是最新的两代版本,市场占有率大于1%,不过时的版本即是24个月官方支持或更新的浏览器
4. 合并配置
- webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
5. 运行指令
npm run build
Css 压缩
1. 下载包
npm i css-minimizer-webpack-plugin -D
2. 配置
- webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");//导入css压缩模块
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
// css压缩
new CssMinimizerPlugin(),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
3. 运行指令
npm run build
html 压缩
默认生产模式已经开启了:html 压缩和 js 压缩
不需要额外进行配置