一、Webpack基础
1.前言
1.1 为什么需要打包工具?
开发时,我们会使用框架(React、Vue),ES6 模块化语法,Less/Sass 等 css 预处理器等语法进行开发。
这样的代码要想在浏览器运行必须经过编译成浏览器能识别的 JS、Css 等语法,才能运行。
所以我们需要打包工具帮我们做完这些事。
除此之外,打包工具还能压缩代码、做兼容性处理、提升代码性能等。
1.2 有哪些打包工具?
- Grunt
- Gulp
- Parcel
- Webpack
- Rollup
- Vite
- ...
目前市面上最流量的是 Webpack,所以我们主要以 Webpack 来介绍使用打包工具
2.Webpack介绍
2.1 作用
Webpack 是一个静态资源打包工具。
它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
输出的文件就是编译好的文件,就可以在浏览器段运行了。
我们将 Webpack 输出的文件叫做 bundle。
2.2 功能
Webpack 本身功能是有限的:
- 开发模式:仅能编译 JS 中的
ES Module语法 - 生产模式:能编译 JS 中的
ES Module语法,还能压缩 JS 代码
2.3 创建webpack项目
2.6.1 项目目录结构
webpack_code # 项目根目录(所有指令必须在这个目录运行)
└── public
├── index.html # 引入dist里的main.js文件
└── src # 项目源码目录
├── css # css文件目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目入口文件
└── webpack.config.js # webpack配置文件2.6.2 下载webpack模块
yarn add webpack webpack-cli -D2.6.3 启动webpack
开发模式
npx 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:指定模式(环境)。--config:指定配置文件
2.4 五大核心概念
| 配置项 | 描述 | 作用 |
|---|---|---|
| entry | 入口 | 指示 Webpack 从哪个文件开始打包 |
| output | 输出 | 指示 Webpack 打包完的文件输出到哪里去,如何命名等 |
| loader | 加载器 | webpack 本身只能处理 js、json 等资源,其他资源需要借助 loader,Webpack 才能解析 |
| plugins | 插件 | 扩展 Webpack 的功能 |
| mode | 模式 | 分为开发模式:development,生产模式:production |
2.5 Webpack 配置文件
在项目根目录下新建文件:webpack.config.js
下面是webpack.config.js基本结构
module.exports = {
// 入口
entry: "",
// 输出
output: {},
// 加载器
module: {
rules: [],
},
// 插件
plugins: [],
// 模式
mode: "",
};Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范
下面是webpack.config.js在项目中最基本的配置,往后会有更多的配置
// 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", // 开发模式
};2.6 开发模式介绍
开发模式顾名思义就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
1.编译代码,使浏览器能识别运行
- 开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
2.代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。
提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
3.处理样式资源
学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源
- Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
- 我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用
- 官方文档找不到的话,可以从社区 Github 中搜索查询
- Webpack 官方 Loader 文档
3.1 处理Css资源
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>Document</title>
</head>
<body>
<h1>hello webpack</h1>
<div class="box">
<div class="son"></div>
<div class="son1"></div>
<div class="son2"></div>
</div>
<script src="../dist/main.js"></script>
</body>
</html>3.1.1 下载包
yarn add css-loader style-loader -Dcss-loader:负责将 Css 文件编译成 Webpack 能识别的模块style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
3.1.2 配置
- test:用来匹配以
.xxx结尾的文件 - use:使用多个loader, 执行顺序是从右到左
- loader:使用单个loader
webpack.config.js
// ...
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
],
},
// ...3.1.3 添加css资源
src/css/index.css
.box{
width: 500px;
height: 500px;
border: 1px solid #000;
}3.1.4 导入css
src/main.js
import "./css/index.css";3.1.5 运行指令
npx webpack打开public/index.html即可看到结果
3.2 处理Less资源
3.2.1 下载包
yarn add less less-loader -D3.2.2 配置
// ...
module: {
rules: [
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
],
},
// ...3.2.3 添加Less资源
src/less/index.css
.box{
.son{
width: 50px;
height: 50px;
background-color: pink;
}
}3.2.4 导入less
src/main.js
import "./less/index.less";3.2.5 运行指令
npx webpack打开public/index.html即可看到结果
3.3 处理Sass和Scss资源
3.3.1 下载包
yarn add sass-loader sass -D3.3.2 配置
// ...
module: {
rules: [
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
// ...3.3.3 添加sass资源
src/scss/index.scss
.box {
.son1 {
width: 50px;
height: 50px;
background-color: blue;
}
}3.3.4 导入
src/main.js
import "./scss/index.scss";3.3.5 运行指令
npx webpack打开public/index.html即可看到结果
3.4 处理Styl资源
3.4.1 下载包
yarn add stylus stylus-loader -D3.4.2 配置
// ...
module: {
rules: [
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
],
},
// ...3.4.3 添加Styl资源
src/styl/index.styl
/* 可以省略大括号、分号、冒号 */
.box
width 100px
height 100px
background-color pink3.4.4 导入
src/main.js
import "./styl/index.styl";3.4.5 运行指令
npx webpack打开public/index.html即可看到结果
4.处理图片资源
过去在 Webpack4 时,我们处理图片资源通过 file-loader 和 url-loader 进行处理
现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源
4.1 配置
// ...
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
}
}
},
],
},
// ...5.修改输出文件目录
5.1 入口文件输出位置
修改output中的filename
webpack.config.js
output: {
path: path.resolve(__dirname, "dist"),
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
},5.2 图片资源输出位置
在相应loader中添加generator配置项,修改filename
- hash:打包后图片的文件名为一串唯一的字符串
- 修改文件名长度
[hash:8],生成字符串长度为8的文件名
- 修改文件名长度
- ext:打包后的文件扩展名与打包前的扩展名一致
- query:添加之前的query参数
// ...
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp)$/,
generator: {
filename: "static/imgs/[hash:8][ext][query]",
},
}
],
},
// ...6.自动删除上次打包内容
在output中添加clean: true
output: {
//...
clean: true,
//...
},7.处理字体图标资源
用到iconfont或者其他字体时,项目中会有一些以ttf或woff结尾的字体文件
7.1 配置
// ...
module: {
rules: [
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:10][ext][query]",
},
},
],
},
// ...type: "asset/resource"和type: "asset"的区别:
type: "asset/resource"相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理type: "asset"相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式
7.2 其他资源
除了字体,项目中可能还会有音频、视频等资源,也属于asset/resource类型,只需将上面代码添加部分内容
// ...
module: {
rules: [
{
test: /\.(ttf|woff2?|mp3|mp4|avi)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:10][ext][query]",
},
},
],
},
// ...8.处理js资源
Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理。
其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。
- 针对 js 兼容性处理,我们使用 Babel 来完成
- 针对代码格式,我们使用 Eslint 来完成
8.1 Eslint
可组装的 JavaScript 和 JSX 检查工具。用来检测 js 和 jsx 语法的工具,可以配置各项功能
8.1.1 配置文件
Eslint配置文件分为以下几种方式
- .eslintrc.*:位于项目根目录,区别在于配置格式不一样
.eslintrc.eslintrc.js.eslintrc.json
package.json中eslintConfig:不需要创建文件,在原有文件基础上写
8.1.2 具体配置
以 .eslintrc.js 配置文件为例:
有parserOptions、rules、extends三个配置项
module.exports = {
// 解析选项
parserOptions: {},
// 具体检查规则
rules: {},
// 继承其他规则
extends: [],
// ...
// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};1.parserOptions
parserOptions: {
ecmaVersion: 6, // ES 语法版本
sourceType: "module", // ES 模块化
ecmaFeatures: { // ES 其他特性
jsx: true // 如果是 React 项目,就需要开启 jsx 语法
}
}2.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 除了少数情况下不会有警告
],
}更多规则详见:规则文档
3.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"],
},
};8.1.3 在Webpack中使用
1.下载包
yarn add eslint-webpack-plugin eslint -D2.定义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 定义变量
},
};3.配置
webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
// ...
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
// ...
};8.1.4 VSCode Eslint 插件
下载此插件不用编译,vscode会自动显示错误
Eslint 忽略文件解决
.eslintignore
# 忽略dist目录下所有文件
dist8.2 Balel
主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
8.2.1 配置文件
配置文件由很多种写法:
babel.config.*:新建文件,位于项目根目录babel.config.jsbabel.config.json
.babelrc.*:新建文件,位于项目根目录.babelrc.babelrc.js.babelrc.json
package.json中babel:不需要创建文件,在原有文件基础上写
Babel 会查找和自动读取它们,以上配置文件只需要存在一个即可
8.2.2 具体配置
以 babel.config.js 配置文件为例:
babel.config.js
module.exports = {
// 预设
presets: [],
};presets 预设
简单理解:就是一组 Babel 插件, 扩展 Babel 功能
@babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。@babel/preset-react:一个用来编译 React jsx 语法的预设@babel/preset-typescript:一个用来编译 TypeScript 语法的预设8
8.2.3 在Webpack中使用
1.下载包
yarn add babel-loader @babel/core @babel/preset-env -D2.定义 Babel 配置文件
babel.config.js
module.exports = {
presets: ["@babel/preset-env"],
};3.配置
webpack.config.js
module.exports = {
module: {
rules: [
// ...
{
test: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
// ...
],
},
};- 运行指令
npx webpack打开打包后的 dist/static/js/main.js 文件查看,会发现箭头函数等 ES6 语法已经转换了
9.处理Html资源
9.1 下载
yarn add html-webpack-plugin -D9.2 配置
webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "public/index.html"),
}),
],
// ...
}之后再打包,dist会有一个index.html文件,和项目中的html结构一致,并且自动引入main.js
10.开发服务器&自动化
devServer会在webpack中搭建一个服务器,默认端口为localhost:3000,自动监视src下的文件,若发现有文件发生变化,会自动打包。这样就不用每次修改完文件手动打包了
10.1 下载
yarn add webpack-dev-server -D10.2 配置
devServer是和entry等同级的配置项
webpack.config.js
module.exports = {
// 开发服务器
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
};11.生产环境介绍
11.1 项目目录
- 主要是在根目录下创建一个config文件夹,将有原来的webpack.config.js放进去,并改名为webpack.dev.js
- 再复制一份改名为webpack.prod.js
├── 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 (包的依赖管理配置文件)11.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",
};运行开发模式的指令:
- server:开启devServer
- --config:指定配置文件
npx webpack serve --config ./config/webpack.dev.js11.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.js11.4 配置运行指令
package.json
{
// ...
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
}
// ...
}12.Css处理
12.1 提取Css成单独文件
Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式
这样对于网站来说,会出现闪屏现象,用户体验不好
我们应该是单独的 Css 文件,通过 link 标签加载性能才好
12.1.1 下载包
yarn add mini-css-extract-plugin -D12.1.2 配置
将之前所有style-loader换成MiniCssExtractPlugin.loader,并注册插件
webpack.prod.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
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"],
},
],
},
plugins: [
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
// ...
],
mode: "production",
};12.2 Css兼容性处理
12.2.1 下载包
yarn add postcss-loader postcss postcss-preset-env -D12.2.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 = {
// ...
module: {
rules: [
{
test: /\.css$/,
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",
],
},
],
},
// ...
};12.2.3 控制兼容性
可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。
{
// 其他省略
"browserslist": ["ie >= 8"]
}想要知道更多的 browserslist 配置,查看browserslist 文档open in new window
以上为了测试兼容性所以设置兼容浏览器 ie8 以上。
实际开发中我们一般不考虑旧版本浏览器了,所以我们可以这样设置:
{
// 其他省略
"browserslist": ["last 2 version", "> 1%", "not dead"]
}12.2.4 合并配置
将之前的兼容loader封装床函数,减少代码冗余
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"),
},
// ...
],
},
// ...
mode: "production",
};12.3 css压缩
默认生成模式html、js已经开始压缩
12.3.1 下载包
yarn add css-minimizer-webpack-plugin -D12.3.2 配置
webpack.prod.js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
// ...
plugins: [
// css压缩
new CssMinimizerPlugin(),
// ...
],
mode: "production",
};