entry(入口)—使用相对路径
指示Webpack从哪个文件开始打包
output(输出)—使用绝对路径
指示webpack打包完的文件输出到哪里,怎么命名
loader(加载器)
webpack本身只能处理js、json等资源,其他资源需要借助loader,webpack才能解析
plugins(插件)
扩展webpack的功能
mode(模式)
主要有两种模式
开发模式:development
生产模式:production
在这个模式下我们主要做两件事:
编译代码,使浏览器能识别运行
开发时我们有样式资源、字体图标、图片资源等,webpack默认都不能处理这些资源,所以我们要加载配置来编译这些资源
代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时更加健壮
output:{
// 所有文件的输出路径
path:path.resolve(__dirname,"dist"), // __dirname代表当前文件的文件夹目录
// 入口文件打包输出文件名
filename:"static/js/main.js",
// 自动清空上次打包的内容
clean:true, // 原理:在打包之前,将path整个目录内容清空,再进行打包
}
webpack本身是不能识别样式资源的,所以我们需要借助loader来帮助webpack解析资源
我们找loader都应该去官方文档找对应的loader,然后使用
官方文档找不到的话,可以从Github中寻找
安装
npm install --save-dev css-loader
npm install --save-dev style-loader
配置
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
test
的值是一个正则表达式,用于匹配文件
use
的值是一个数组,用于配置所用loader
信息,loader
的执行顺序为从右到左
css-loader
将css资源编译成common.js
的模块到js中
style-loader
将js中css通过创建style
标签添加html
文件中生效
过去在webpack4时,我们处理图片资源通过file-loader
和url-loader
进行处理
现在webpack5已经将两个loader功能内置到webpack里,我们只需要简答配置即可处理资源
base64的优缺点
优点:
网页中使用base64格式的图片时,不用再请求服务器调用图片资源,减少了服务器访问次数
base64编码的字符串,更适合不同平台、不同语言的传输
缺点:
base64格式的文本内容较多,存储在数据库中增大了数据库服务器的压力
网页加载图片虽然不用访问服务器了,但因为base64格式的内容太多,所以加载网页的速度会降低,可能会影响用户的体验。
base64无法缓存,要缓存只能缓存包含base64的文件,比如js或者css,这比直接缓存图片要差很多,而且一般HTML改动比较频繁,所以等同于得不到缓存效益。
算法是编码, 不是压缩, 编码后只会增加字节数,但是算法简单, 几乎不会影响效率,算法可逆, 解码很方便, 不用于私密信息通信;
{
test:/\.(png|jpe?g|gif|webp|svg)$/
type:"asset",
parser:{
dataUrlCondition:{
// 小于10kb的图片转为bas64
// 优点:减少请求数量,缺点:体积会变大
maxSize:10 *1024 // 10kb
}
}
}
如果不对输出目录进行设置,我们会发现打包之后的图片和代码文件处于一个文件夹内,这样子会显得很乱
所以,我们需要修改图片的输出目录,将所有图片
{
test:/\.(png|jpe?g|gif|webp|svg)$/
type:"asset",
parser:{
dataUrlCondition:{
// 小于10kb的图片转为bas64
// 优点:减少请求数量,缺点:体积会变大
maxSize:10 *1024 // 10kb
}
},
generator:{
// 输出图片的名称
filename:"static/images/[hash][ext][query]"
}
}
【举例】
一张打包好的图片,文件名:074das1d6546131as6d.png
hash
即为074das1d6546131as6d
ext
即为文件后缀,png
query
是携带的参数,url地址?后的查询参数
现在有一种感觉,打包之后的图片名字很长,我们可以修改hash
值的长度进行修改
generator:{
// 输出图片的名称
filename:"static/images/[hash:10][ext][query]"
}
[hash:10]
就能将hash值取前10位
{
test:/\.(ttf|woff2?|mp3|mp4)$/,
// 这样就不会转为base64形式
type:"asset/resource",
generator:{
// 输出名称
filename:"static/media/[hash][ext][query]"
}
}
webpack对js处理是有限的,只能编译js中ES模块,不能编译其他语法,导致js不能在IE等浏览器中运行,所以我们希望做一些兼容处理
针对js兼容性处理,我们使用babel来完成
针对代码格式,我们使用Eslint来实现
我们先完成Eslint,检测代码格式无误后,在babel做代码兼容性处理
可组装的JavaScript和JSX检查工具
我们使用Eslint,关键是写Eslint配置文件,里面写上rules规则,将来运行Eslint时就会以写的规则对代码进行检查
npm install eslint-webpack-plugin eslint --save-dev
然后把插件添加到你的 webpack 配置
注意:插件是需要引入的
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
// ...
plugins: [new ESLintPlugin({...})],
// ...
};
new ESLintPlugin
参数配置:
详细配置:https://webpack.docschina.org/plugins/eslint-webpack-plugin
context
类型:
string
默认值:
compiler.context
指定文件根目录,类型为字符串。需要检测的文件
一般的写法:
path.resolve(__dirname,'src)
,检测根目录下,src
文件夹下的文件
…
配置文件
配置文件有很多的写法:
.eslintrc
.eslintrc.js
.eslintrc.json
package.json
中eslintConfig
,无需创建文件,在原有文件基础上写
区别在于配置格式不一样
Eslint会查找和自动读取它们,所以以上配置文件只需一个存在即可
具体配置
以.eslint.js
配置文件为例:
module.export = {
// 解析选项
parserOptions:{},
// 具体检查规则
rules:[].
// 继承其他规则
extends:[],
// ...
}
parserOptions解析选项
parserOptions:{
ecmaVersion:6 // ES语法版本
sourceType:"module" // ES模块化
ecmaFeatures:{
jsx:true // 如果是react项目,就需要开启jsx语法
}
}
rules 具体规则
"off"
或者0
—— 关闭规则
"warn"
或者1
—— 开启规则,使用警告级别的错误:warn
(不会导致程序退出)
"error"
或者2
—— 开启规则,使用错误级别的错误:error
(当被触发的时候,程序会退出)
rules:{
semi:"error", // 禁止使用分号
"default-case":[
"warn", // 要求switch语法中有default,否则警告
{commentPattern:'^no default$'} // 允许在最后注释no default,就不会警告了
]
// ....
}
extends 继承
开发中有一点点写rules规则太费劲,所以有更好的办法,继承现有的规则
{
// 例如在react项目中
extends:['react-app']
}
主要将ES6语法编写的代码转化为向后兼容的javascript语法,以便能够运行在当前和就版本的浏览器或者其他环境
npm install -D babel-loader @babel/core @babel/preset-env webpack
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
exclude
:排除哪些文件不进行处理
预设可以直接写在webpack的配置中,也可以新建文件进行配置
配置文件
babel.config.js
babel.config.json
.babelrc
.babelrc.js
.babelrc.json
Babel会查找和自动读取它们,所以以上配置文件只需要存在一个即可
具体配置
我们以babel.config.js
为例
module.exports = {
// 预设
presets:[]
}
presets预设,简单理解:就是一组Babel插件,扩展Babel功能
@babel/preset-env
:一个智能预设,允许使用最新的javascript
@babel/preset-react
:一个用来编译React.jsx语法的预设
@babel/preset-typescript
:一个用来编译Typescript语法的预设
在之前的代码中,我们都是在public/index.html
中引入打包后的js
文件,但是对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包,通过手写的路径就出现问题,我们需要自动导包
npm install --save-dev html-webpack-plugin
该插件将为你生成一个 HTML5 文件, 在 body 中使用 script
标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中
// 配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js',
},
plugins: [new HtmlWebpackPlugin({
// 模板:以public/index.html文件创建新的html文件
// 新的html文件特点:1.结构和原来一致 2. 自动引入打包输出的资源
template:path.resolev(___dirname,"public.index.html")
})],
};
每次写完代码都需要手动输入指令才能编译代码,太麻烦,我们希望一切自动化
开发服务,不会输出资源,在内存中编译打包的,因此在目录中不会出现打包后的文件
npm i webpack-dev-server -D
devServer:{
host:'localhost', // 启动服务器域名
port:'3000', // 启动服务器端口号
open:true // 是否自动打开浏览器
}
启动服务器
之前打包使用的命令行为npx webpack
开启服务器,需要使用npx webpack serve
生产模式是开发完成代码之后,我们需要得到代码将来部署上线
这个模式下我们主要对代码进行优化,让其运行性能更好
优化主要从两个角度:
优化代码运行性能
优化代码打包速度
css文件目前被打包到js文件中,当js文件加载时,会创建一个style标签生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
我们应该是单独的css文件,通过link标签加载
MiniCssExtractPlugin
本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。
本插件基于 webpack v5 的新特性构建,并且需要 webpack 5 才能正常工作。
npm install --save-dev mini-css-extract-plugin
建议 mini-css-extract-plugin
与 css-loader
一起使用。
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()], // 第一步
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"], // 第二步
},
],
},
};
如果需要规范css文件的位置,可以再plugins
中添加参数进行修改
plugins:[
new MiniCssExtractPlugin({
filename:'static/css/main.css'
})
]
npm install --save-dev postcss-loader postcss
然后添加本 loader 的相关配置到你的 webpack
的配置文件
此处需要注意loader
的位置顺序:
css-loader
> postcss-loader
> less|sass等预处理loader
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// 其他选项
},
],
],
},
},
},
],
},
],
},
}
我们还需要进行兼容的配置(设置最低兼容的程度),在package.json
中设置
{
...
"browserslist":[
"ie >= 9"
]
}
以上配置是兼容到ie9及以上
但是我们实际上会这么写(取数组中所有约束的交集):
{
...
"browserslist":[
"last 2 version", 所有浏览器近两个版本
"> 1%", 覆盖99%的浏览器
"not dead" 未停止维护的
]
}
在配置样式的loader
的时候,我们发现有多行代码是重复的,为了代码的简洁和提高其复用性,我们将其进行封装
function getStyleLoader() {
return [
...loader重复的配置
]
}
CssMinimizerWebpackPlugin
使用 cssnano 优化和压缩 CSS,在 source maps 和 assets 中使用查询字符串会更加准确,支持缓存和并发模式下运行。
npm install css-minimizer-webpack-plugin --save-dev
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
optimization: {
minimizer: [
// 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
// `...`,
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
这将仅在生产环境开启 CSS 优化。
如果还想在开发环境下启用 CSS 优化,请将 optimization.minimize
设置为 true
:
module.exports = {
optimization: {
// [...]
minimize: true,
},
};
更简单的方法就是在plugns
中直接配置
plugins:[new CssMinimizerPlugin()]