webpack笔记
简介
- 开发时,我们会使用框架(react、vue),es6模块化语法,less/sass等css预处理器语法进行开发。这样的代码要想在浏览器运行必须经过编译成浏览器能识别的js、css等语法才能运行,所以我们需要打包工具帮我们做完这些事
- 除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等
基本使用
- webpack本身功能有限
- 开发模式:能编译js中的
ES Module
语法 - 生产模式:能编译js中的
ES Module
语法,还能压缩js代码
- 开发模式:能编译js中的
- 基本指令
1
2
3
4
5
6
7
8
9
10
11# 初始化package.json
npm init -y
# 下载依赖
npm i webpack webpack-cli -D
# 开发模式
npm webpack ./src/main.js --mode=development
# 生产模式
npx webpack ./src/main.js --mode=productionnpx webpack:是用来运行本地安装webpack包的
./src/main.js:指定webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来
–mode=xxx:指定模式(环境)
基本配置
5大核心概念
- entry(入口):指示webpack从哪个文件开始打包
- output(输出):指示webpack打包万的文件输出到哪里去,如何命名等
- loader(加载器):webpack本身只能处理js、json等资源,其他资源需要借助loader,webpack才能解析
- plugins(插件):扩展webpack的功能
- mode(模式):
- 开发模式:development
- 生产模式:production
配置文件
- 项目根目录创建
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// nodejs核心模块,专门用来处理路径问题
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
// __dirname指配置文件的当前位置
path: path.resolve(__dirname, "dist"),
// 如果我们在根目录创建config文件夹,并把配置文件丢进去
// 同时希望dist文件夹生成在根目录,就要../到上一层输出dist文件夹
// path: path.resolve(__dirname, "../dist"),
filename: "main.js"
},
module: {
rules: [
// loader的配置
]
},
plugins: [],
mode: "development"
} - 终端在项目目录中,输入
npx webpack
指令,就会寻找配置文件并加载里面的配置
开发模式
- 编译代码,使浏览器能识别运行
- 开发时,我们有样式资源、字体图标、图片资源、html资源等,webpack默认都不能处理这些资源,所以我们要加载配置来编译这些资源
- 代码质量检查,树立代码规范
- 提前检查代码的一些隐患,让代码运行时能更加健壮
- 提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观
处理样式资源
处理css资源
- 安装
css-loader
与style-loader
,已安装请忽略1
2npm install --save-dev css-loader
npm install --save-dev style-loader - 创建一个css文件,引入到
main.js
,通常是入口文件1
2
3// 想要webpack打包资源,必须引入该资源
// 只是用来打包,不需要定义变量接收它
import "./css/index.css" - 接着到配置文件中,注意use配置中有
style-loader
,如果只安装css-loader
肯定会报错1
2
3
4
5
6
7
8
9
10
11
12
13
14module.exports = {
module: {
rules: [
{
test: /\.css$/, // 只检测.css文件
use: [
// 执行顺序,从右到左(从下到上)
"style-loader", // 将js中的css通过创建style标签添加到html文件
"css-loader", // 将css资源编译成commonjs模块到js中
],
},
],
},
}; - 输入
npx webpack
指令,重新加载配置
处理less资源
- 安装
less
与less-loader
,已安装请忽略1
npm install less less-loader --save-dev
- 创建一个less文件,引入到
main.js
,通常是入口文件1
2
3// 想要webpack打包资源,必须引入该资源
// 只是用来打包,不需要定义变量接收它
import "./less/index.less" - 接着到配置文件中,注意官方文档用的是
loader: [...]
,这种方式只能使用1个loader,所以要改成use
,它可以使用多个loader1
2
3
4
5
6
7
8
9
10
11
12
13
14
15module.exports = {
module: {
rules: [
{
test: /\.less$/,
// loader: ['style-loader', 'css-loader', 'less-loader'],
use: [
'style-loader',
'css-loader',
'less-loader' // 将less编译成css
]
},
],
},
}; - 输入
npx webpack
指令,重新加载配置
处理sass和scss资源
- 安装
sass
与sass-loader
,已安装请忽略1
npm install sass-loader sass --save-dev
- 创建sass与scss文件,引入到
main.js
,通常是入口文件1
2
3
4// 想要webpack打包资源,必须引入该资源
// 只是用来打包,不需要定义变量接收它
import "./sass/index.sass"
import "./sass/index.scss" - 接着到配置文件中,添加sass-loader配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/, // 使用[]表示检测.sass或.scss文件
use: [
'style-loader',
'css-loader',
'sass-loader' // 将sass编译成css
]
},
],
},
}; - 输入
npx webpack
指令,重新加载配置
处理stylus资源
- 国内几乎没什么人用,跳过吧
处理图片资源
- 过去在webpack4时,我们处理图片资源通过
file-loader
和url-loader
进行处理 - 现在webpack5已经将两个loader功能内置到webpack里了,只需要简单配置即可处理图片资源
- 官方文档搜资源模块,有个处理图片的功能,主要是把图片转成base64(字符串),减少向服务器请求图片的次数,缺点是图片转成base64体积会变大,但我们只处理10kb以下的图片,那么增加个1~2kb,其实也无所谓
1
2
3
4
5
6
7
8
9
10
11
12
13module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 10kb
}
}
}
]
}
修改输出路径
- 有时候,我希望输出的文件,各自在自己的文件夹内,而不是全部挤在一起
- 首先是修改js输出路径,它的位置在
output
内,我们需要修改的是filename
,通常只有main.js
这个文件filename: "static/js/main.js"
- 上面提到处理图片资源,但却少了输出路径,我们也加上吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 10kb
}
},
generator: {
// 输出图片的名称
// hash表示生成的图片名是哈希值,不会重名,10是取10位
// ext是保留后缀名,比如.jpg等
// query是保留携带参数
filename: "static/images/[hash:10][ext][query]"
}
}
]
}
自动清空上次打包内容
- 每次想看打包效果,总需要提前删除打包好的文件,在输入打包命令,这太麻烦了。于是webpack提供了一个清空参数,原理是打包前,将output整个目录内容清空,再进行打包
1
2
3
4
5
6module.exports = {
//...
output: {
clean: true, // 在生成文件之前清空 output 目录
},
};
处理字体图标资源
- 主要讲阿里巴巴的字体图标,下载后选哪种引入方式,多色字体图标毫无疑问选
Symbol
,单色字体选哪个都行,使用Font class
引入会简单一些,这次选Font class
引入。总共需要把4个文件放进项目,iconfont.css
放css文件夹内,那三个字体文件放fonts文件夹内,修改下iconfont.css
路径问题 - 别忘了把
iconfont.css
导入到main.js
😉 - 字体图标配置和处理图片资源差不多,但我们不需要转换base64,所以要改成
asset/resource
,它会原封不动把字体图标输出出去。当然,输出路径我们也需要,修改成media可以了,这是视频的意思,下面会解释1
2
3
4
5
6
7
8
9
10
11module: {
rules: [
{
test: /\.(ttf|woff2?)$/,
type: 'asset/resource', // 不需要转换base64
generator: {
filename: "static/media/[hash:10][ext][query]"
}
}
]
}
处理其他资源
- 考虑到未来会增加很多资源,每个资源都进行分类,那太麻烦了,不如统一丢到media文件夹内,我们需要做的只是添加后缀名
1
2
3
4
5
6
7
8
9
10
11module: {
rules: [
{
test: /\.(ttf|woff2?|mp[34]|avi)$/,
type: 'asset/resource', // 不需要转换base64
generator: {
filename: "static/fonts/[hash:10][ext][query]"
}
}
]
}
处理js资源
webpack对js处理是有限的,只能处理模块化语法,像是箭头函数、三点运算符等不支持,不支持的结果是原封不动输出,对IE兼容性会产生问题,然而2022年6月微软宣布彻底结束IE浏览器,由于缺少安全补丁支持,早晚会漏洞百出,逼迫政府与企业升级浏览器,对我们开发者来说是个好事,不需要在考虑兼容IE了,可以放心使用ES6语法
ESLint
- eslint是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码
- 安装
eslint
和eslint-webpack-plugin
,已安装请忽略1
npm install eslint eslint-webpack-plugin --save-dev
- plugin和loader使用有点不一样,loader可以直接用,plugin需要先引入后使用;所有插件都是构造函数,最终都是new调用
1
2
3
4
5
6
7
8
9
10const ESLintPlugin = require('eslint-web-pack-plugin');
module.exports = {
plugins: [
new ESLintPlugin({
// 检测哪些文件
context: path.resolve(__dirname, "src")
})
],
}; - 输入
npx webpack
指令,上面会报错,我们还需要配置eslintrc.js
文件,在根目录下创建此文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15module.exports = {
// 继承Eslint规则
extends: ["eslint: recommended"],
env: {
node: true, // 启动node中全局变量
browser: true // 启动浏览器中全局变量
},
parserOptions: {
ecmaVersion: 6, // 使用es6语法
sourceType: "module" // 用es module
},
rules: {
"no-var": 2 // 不能使用var定义变量
}
}; - 上面完成后,webpack里的eslint插件可以使用了,但是编辑器安装的eslint插件会检测打包后的js文件,这个文件用的是var定义变量,此时文件会报错,我们需要写一个
.eslintignore
忽略文件,有点像git的忽略文件,这里写的dist
是webpack配置的输出文件夹,将会忽略下面的全部文件;写好之后依旧会报错,重启下编辑器看看1
dist
Babel
- 不需要考虑IE兼容问题了,跳过
处理html文件
- 安装
HtmlWebpackPlugin
,已安装请忽略1
npm install --save-dev html-webpack-plugin
- 引入与调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const HtmlWebpackPlugin = require('html-web-pack-plugin');
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'static/js/main.js',
},
plugins: [
new HtmlWebpackPlugin({
// 模版:以public/index.html文件为模版,创建新的html文件
// 新的html文件特点:1.结构和原来一致 2.自动引入打包输出的资源
template: path.resolve(__dirname, "public/index.html")
})
],
}
本地服务器&自动化
- 每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化
- 安装
webpack-dev-server
,它是自动化工具,监视我们的文件,一旦发生改变自动重新打包,已安装请忽略1
npm i webpack-dev-server -D
- 配置本地服务器
1
2
3
4
5
6
7
8module.exports = {
// 本地服务器:它不会输出打包资源,而是在内存中编译打包
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true // 是否自动打开浏览器
}
} - 输入
npx webpack serve
指令,开启本地服务器,这时会弹出一个页面 - 点击正在运行的终端窗口,按下组合键
ctrl + c
终止服务器
生产模式
- 开发完代码后,我们需要将打包的代码部署上线,以及做一些优化提升性能;开发与生产模式都有各自的配置文件,起到不冲突的作用,下面说一下开发与生产的区别
- 开发模式不需要输出,因为我们的本地服务器是在内存中编译
1
2
3
4
5
6
7
8module.exports = {
output: {
// 开发模式没有输出
path: undefined,
// 文件名需要指定
filename: "static/js/main.js"
}
} - 我们把开发与生产配置文件放在config文件夹里,分别起不同名字,开发配置文件名
webpack.dev.js
,生产配置文件名webpack.prod.js
,--config
表示指定配置文件在哪里,下面是开发模式的终端指令1
npx webpack serve --config ./config/webpack.dev.js
- 生产模式需要指定输出,上面文章有提到不重复说明了,主要是修改模式
1
2
3module.exports = {
mode: "production"
} - 我们只管输出打包文件,不需要运行服务器,下面是生产模式的终端指令
1
npx webpack --config ./config/webpack.prod.js
- 我可不希望每次输入一大串指令运行,修改下
package.json
的启动命令,简化指令后就非常方便了- 开发模式:
npm run dev
- 生产模式:
npm run build
1
2
3
4
5
6
7{
"scripts": {
"start": "npm run dev",
"dev": "web-pack serve --config ./config/web-pack.dev.js",
"build": "web-pack --config ./config/web-pack.prod.js"
}
}
- 开发模式:
提取css成单独文件
- css文件目前被打包到js文件中,当js文件加载时,才会创建一个style标签来生成样式。对于网站来说,会出现闪屏现象,用户体验不好,我们应该打包成单独css文件,通过link标签加载性能才好
- 安装
mini-css-extract-plugin
,本插件需要webpack 5才能正常工作1
npm install --save-dev mini-css-extract-plugin
- 回顾一下上面的笔记,有一节处理样式资源,讲的是处理css、sass、less文件,它们都是依赖
style-loader
转成style标签插进html,这不是我们想要的结果,我们需要替换成mini-css
插件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
// 执行顺序,从右到左(从下到上)
// "style-loader",
MiniCssExtractPlugin.loader, // 提取css成单独文件
"css-loader",
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "static/css/main.css", // 它是输出路径
})
],
}; - 如果还有闪屏现象,先停止本地服务器,重新打包一次,再启动本地服务器。还有闪屏现象,就要考虑是不是图片太大的问题,或者配置文件写的不对
css兼容性处理
- 所谓的兼容性处理,全是为了兼容IE浏览器,上文已提过微软彻底停止IE浏览器,不需要特意去学了
- 好吧,执意要学的话,提供两种思路
- autoprefixer:它是编辑器的插件,通常跟预处理器一起使用,自动生成兼容性前缀
- postcss-loader:它是webpack兼容css的功能,你需要分别在webpack与package配置文件中进行配置
封装样式loader函数
- 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
36function getStyleLoader(pre){
return [
MiniCssExtractPlugin.loader, //提取css成单独文件
"css-loader", // 将css资源编译成commonjs模块到js中
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", //解决大多数样式兼容性问题
]
}
}
},
pre, // 将预处理器编译成css
].filter(Boolean); // 过滤没有传值的pre
}
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: getStyleLoader(),
},
{
test: /\.less$/,
use: getStyleLoader("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoader("sass-loader"),
},
],
}
}
css压缩
- 减少css代码体积,让代码只显示在一行
- 安装
css-minimizer
插件,已安装请忽略1
npm install css-minimizer-webpack-plugin --save-dev
- 引入与调用
1
2
3
4
5const CssMinimizerPlugin = require("css-minimizer-web-pack-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
};
html和js压缩
- 生产模式默认开启:html压缩和js压缩
- 不需要额外进行配置
高级部分暂时跳过