# Webpack5实战教程
尚硅谷新版Webpack5实战教程(从入门到精通)
https://www.bilibili.com/video/BV1e7411j7T5
尚硅谷前端Webpack5教程(高级进阶篇)
https://www.bilibili.com/video/BV1cv411C74F
笔记分享:
https://lab.puji.design/webpack-getting-started-manual/
## 目录
1. 课程简介
2. Webpack简介
3. Webpack初体验
4. Webpack开发环境基本配置
5. Webpack生产环境基本配置
6. Webpack优化配置
7. Webpack原理分析
8. Webpack5介绍
## 1、课程简介
### 1.1、知识点
- webpack5
- dll
- production
- development
- eslint
- babel
- pwa
- optimization
- resolve
- HMR
- loader
- plugin
- devtool
- 性能优化
- tree shaking
- code split
- caching
- lazy loading
- library
- shimming
### 1.2、环境配置
```
Node.js >= 10
webpack >= 4.26
```
### 1.3、预备知识
- Node.js
- NPM
- ES6
## 2、webpack简介
### 2.1、webpack是什么
Webpack:
- 一种前端资源构建工具;
- 一个静态模块打包器(module bundler).
在webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理
它根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)

### 2.2、webpack五个核心概念
1. entry: 入口
2. output: 输出
3. loader:处理非js文件,翻译工作
4. plugins 插件,执行范围更广的任务,打包优化,压缩,定义环境中的变量等
5. mode 模式
- development
- 本地调试
- 会将process.env.NODE_ENV的值设置为development
- 启用NamedChunksPlugin
- 启用NamedModulesPlugin
- production
- 上线运行
- 会将process.env.NODE_ENV的值设置为production
- 启用FlagDependencyUsagePlug
- 启用FlagDependencyUsagePlugin
- 启用FlagIncludedChunksPlugin
- 启用ModuleConcatenationPlugin
- 启用NoEmitOnErrorsPlugin
- 启用TerserPlugin
## 3、webpack初体验
### 3.1、初始化项目
```bash
mkdir webpack-demo
cd webpack-demo
# 初始化项目目录
npm init -y
# 安装webpack
cnpm i webpack webpack-cli -D
```
项目目录
```bash
$ tree
.
├── package.json
└── src
└── index.js
```
src/index.js
```js
function add(x, y){
return x + y;
}
console.log(add(1, 2));
```
依赖 package.json
```json
{
"devDependencies": {
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
}
}
```
打包
```bash
# 开发环境
$ npx webpack ./src/index.js -o ./dist --mode=development
asset main.js 1.25 KiB [emitted] (name: main)
./src/index.js 64 bytes [built] [code generated]
webpack 5.72.1 compiled successfully in 74 ms
# 生产环境
$ npx webpack ./src/index.js -o ./dist --mode=production
asset main.js 15 bytes [emitted] [minimized] (name: main)
./src/index.js 64 bytes [built] [code generated]
webpack 5.72.1 compiled successfully in 201 ms
```
### 3.2、导入json资源
```
src
├── data.json
└── index.js
```
data.json
```json
{
"name": "Tom",
"age": 23
}
```
index.js
```js
import data from './data.json';
function add(x, y){
return x + y;
}
console.log(add(1, 2));
console.log(data);
```
运行打包后的代码
```bash
$ node dist/main.js
3
{ name: 'Tom', age: 23 }
```
### 3.3、结论
- webpack能处理js、json资源,不能处理css、img等其他资源
- 生产环境和开发环境将ES6模块化编译成浏览器能识别的模块化
- 生产环境比开发环境多了一部压缩js代码
### 3.4、webpack配置文件
构建工具基于node.js环境运行,模块化采用commonjs
一个基本的配置
webpack.config.js
```js
// 用来处理路径
const path = require('path');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
// 输出文件名
filename: 'bundle.js',
// 输出路径 __dirname node.js变量,当前文件的目录绝对路径
path: path.resolve(__dirname, 'dist'),
},
// loader配置
module: {
rules: [],
},
// 插件配置
plugins: [],
// 模式
mode: 'development',
// mode: 'production',
};
```
### 3.5、打包样式资源-css文件
安装处理css的loader
```bash
$ cnpm i style-loader css-loader -D
```
项目结构
```
$ tree -I "node_modules"
.
├── dist
│ ├── bundle.js
│ └── index.html
├── package.json
├── src
│ ├── index.css
│ └── index.js
└── webpack.config.js
```
src/index.js
```js
// 引入样式资源
import './index.css';
```
src/index.css
```css
html,
body {
padding: 0;
margin: 0;
height: 100%;
background-color: pink;
}
```
webpack.config.js
```js
// 用来处理路径
const path = require('path');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
// 输出文件名
filename: 'bundle.js',
// 输出路径 __dirname node.js变量,当前文件的目录绝对路径
path: path.resolve(__dirname, 'dist'),
},
// loader配置
module: {
rules: [
{
// 正则匹配文件名
test: /\.css$/,
// 处理文件的loader
// 执行顺序:从右到左,从下到上
use: [
// 创建style标签,插入到head中
'style-loader',
// 加载css文件,变成commonjs模块,内容是样式字符串
'css-loader',
],
},
],
},
// 插件配置
plugins: [],
// 模式
mode: 'development',
// mode: 'production',
};
```
index.html
```html
Document
```
执行打包命令
```bash
$ npx webpack
```
打开index.html 文件,可以看到css样式已经生效(右键->检查元素)
js动态生成了style标签
```html
Document
```
### 3.6、打包样式资源-less文件
```bash
$ cnpm i less less-loader -D
```
src/index.js
```js
// 引入less样式资源
import './index.less';
```
src/index.less
```css
html,
body {
padding: 0;
margin: 0;
height: 100%;
background-color: pink;
}
```
新增配置 webpack.config.js
```js
// webpack.config.js
// 用来处理路径
const path = require('path');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
// 输出文件名
filename: 'bundle.js',
// 输出路径 __dirname node.js变量,当前文件的目录绝对路径
path: path.resolve(__dirname, 'dist'),
},
// loader配置
module: {
rules: [
// 处理less文件
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
// 将less编译成css
'less-loader',
],
},
],
},
// 插件配置
plugins: [],
// 模式
mode: 'development',
// mode: 'production',
};
```
执行打包命令
```bash
$ npx webpack
```
### 3.7、打包Html资源
- loader: 1. 下载; 2.使用(配置loader)
- plugins: 1. 下载; 2.引入;3.使用
```
cnpm i html-webpack-plugin -D
```
默认创建一个空的HTML文件,自动引入打包输出的所有资源(js/css)
默认输出的HTML
```html
Webpack App
```
自定义HTML
```js
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
// loader配置
module: {},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 模式
mode: 'development',
// mode: 'production',
};
```
src/index.html
```html
Webpack
```
执行打包命令之后输出
```html
Webpack
```
### 3.8、打包图片资源
安装依赖
```
cnpm i html-loader -D
```
项目结构
```bash
$ tree -I node_modules
.
├── package.json
├── src
│ ├── index.html
│ ├── index.js
│ ├── index.less
│ └── weibo.png
└── webpack.config.js
```
src/index.js
```js
// 引入less样式资源
import './index.less';
// js引入图片资源
import weibo from './weibo.png';
console.log(weibo);
// http://127.0.0.1:5500/dist/images/7f1a8e356f.png
```
src/index.less
```less
html,
body {
padding: 0;
margin: 0;
height: 100%;
// background-color: pink;
}
.box {
width: 100px;
height: 100px;
// css引入图片资源
background-image: url('./weibo.png');
// 替换为:background-image: url(/dist/images/7f1a8e356f.png);
background-size: 100% 100%;
background-repeat: no-repeat;
}
```
src/index.html
```html
Webpack
```
配置文件 webpack.config.js
webpack5默认会处理图片资源,webpack4需要单独配置
|webpack5 | webpack4 | 说明
|-|-|-
asset/resource | file-loader | 发送一个单独的文件并导出 URL
asset/inline | url-loader | 导出一个资源的 data URI
asset/source | raw-loader | 导出资源的源代码
asset | url-loader | 在导出一个 data URI 和发送一个单独的文件之间自动选择。
webpack4 配置
```js
{
module: {
rules: [
// 默认无法处理HTML中的图片
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
// 使用一个loader,如果使用多个loader用use
loader: 'url-loader',
options: {
// 图片大小小于8kb,就会被base64编码
// 优点:减少请求数量,减轻服务器压力
// 缺点:js体积会更大, 文件请求速度更慢
limit: 8 * 1024,
// 问题:url-loader默认使用es6模块解析,而html-loader引入图片是commonjs
// 解析时会出现[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule: false,
// 自定义命名 取hash前10位
name: '[hash:10].[ext]'
}
},
// 处理html中的图片, 引入img,让后续loader解析
{
test: /\.html$/i,
loader: 'html-loader',
},
]
}
}
```
package.json
```json
{
"devDependencies": {
"css-loader": "^6.7.1",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.2",
"less-loader": "^11.0.0",
"style-loader": "^3.3.1",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
}
}
```
webpack5配置
```js
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
// 自定义资源文件名
assetModuleFilename: 'images/[hash:10][ext][query]',
},
// loader配置
module: {
rules: [
// 处理less文件
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader'],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
// 默认: 小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。
type: 'asset',
},
// 处理html中的图片
{
test: /\.html$/i,
loader: 'html-loader',
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 模式
mode: 'development',
// mode: 'production',
};
```
### 3.9、打包字体资源
可以从iconfont([https://www.iconfont.cn/](https://www.iconfont.cn/))网站下载字体文件
打包后的项目结构
```
$ tree -I node_modules
.
├── dist
│ ├── bundle.js
│ ├── images
│ │ ├── 5b0edd384b.ttf
│ │ ├── 969b5fedf8.woff
│ │ └── d79bd05095.woff2
│ └── index.html
├── package.json
├── src
│ ├── iconfont
│ │ ├── iconfont.css
│ │ ├── iconfont.js
│ │ ├── iconfont.json
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ └── iconfont.woff2
│ ├── index.html
│ ├── index.js
└── webpack.config.js
```
src/index.js
```js
// 引入css样式资源
import './iconfont/iconfont.css';
```
src/index.html
```html
Webpack
```
webpack.config.js
webpack4
```js
{
// 排除资源
exclude: /\.(js|less|html)$/i,
type: 'file-loader',
options: {
// 自定义命名 取hash前10位
name: '[hash:10].[ext]'
}
},
```
webpack5
```js
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// webpack配置
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
// 自定义资源文件名
assetModuleFilename: 'images/[hash:10][ext][query]',
},
// loader配置
module: {
rules: [
// 处理css文件
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
// 处理less文件
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader'],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset',
},
// 处理html文件,加载其中的图片
{
test: /\.html$/i,
loader: 'html-loader',
},
// 处理字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 模式
mode: 'development',
// mode: 'production',
};
```
## 4、开发环境基本配置
### 4.1、devServer
开发服务器,自动化开发(自动编译,自动打开浏览器,自动刷新浏览器)
特点:只会在内存中编译打包,不会有任何输出
```bash
npm install webpack-dev-server --save-dev
```
webpack4配置
```js
module.exports = {
devServer: {
// 项目构建后路径
contentBase: resolve(__dirname, 'dist'),
// 启动gzip压缩
compress: true,
// 端口号
port: 3000,
// 自动打开浏览器
open: true
}
}
```
webpack5配置
```js
module.exports = {{
// 开发服务器配置
devServer: {
// 从目录提供静态文件
static: {
directory: path.join(__dirname, "public"),
publicPath: "/",
},
// 启动后打开浏览器
open: true,
// 监听请求的端口号
port: 8080,
},
}
```
为了方便启动,可以配置启动命令
package.json
```json
{
"scripts": {
"dev": "webpack serve",
"build": "webpack"
},
}
```
启动开发服务器
```
npm run dev
```
### 4.2、webpack开发环境
1. 提升开发效率
2. 处理js、css、less、图片、字体文件
webpack.config.js 完整配置
```js
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// webpack配置
module.exports = {
// 入口文件
entry: "./src/index.js",
// 输出
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
// 自定义资源文件名
assetModuleFilename: "images/[hash:10][ext][query]",
},
// 开发服务器配置
devServer: {
// 从目录提供静态文件
static: {
directory: path.join(__dirname, "public"),
publicPath: "/",
},
// 启动后打开浏览器
open: true,
// 监听请求的端口号
port: 8080,
},
// loader配置
module: {
rules: [
// 处理css文件
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
// 处理less文件
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset",
},
// 处理html文件,加载其中的图片
{
test: /\.html$/i,
loader: "html-loader",
},
// 处理字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
// 模式
mode: "development",
// mode: 'production',
};
```
## 5、生产环境基本配置
目前存在的问题
1. css通过js动态生成,会出现闪屏现象
2. 代码没有压缩
3. 浏览器兼容性问题
### 5.1、提取css成单独的文件
```bash
npm i mini-css-extract-plugin -D
```
完整配置
```js
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// webpack配置
module.exports = {
// 入口文件
entry: "./src/index.js",
// 输出
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
// 自定义资源文件名
assetModuleFilename: "images/[hash:10][ext][query]",
// 在生成文件之前清空 output 目录
clean: true,
},
// 开发服务器配置
devServer: {
// 从目录提供静态文件
static: {
directory: path.join(__dirname, "public"),
publicPath: "/",
},
// 启动后打开浏览器
open: true,
// 监听请求的端口号
port: 8080,
},
// loader配置
module: {
rules: [
// 处理css文件
{
test: /\.css$/i,
use: [
// 创建style标签,将样式放入style标签中
// "style-loader",
// 提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
"css-loader",
],
},
// 处理less文件
{
test: /\.less$/i,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
"less-loader",
],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset",
},
// 处理html文件,加载其中的图片
{
test: /\.html$/i,
loader: "html-loader",
},
// 处理字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
// 模式
mode: "development",
// mode: 'production',
};
```
### 5.2、css兼容性处理
```
npm i postcss postcss-loader postcss-preset-env -D
```
browserslist: [https://github.com/browserslist/browserslist](https://github.com/browserslist/browserslist)
通过 NODE_ENV 判断环境, 默认生产环境
package.json
```json
{
"browserslist": {
"development": [
"last 1 version"
],
"production": [
"last 1 version",
"> 1%",
"ie 10"
]
}
}
```
完整配置
```js
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// webpack配置
module.exports = {
// 入口文件
entry: "./src/index.js",
// 输出
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
// 自定义资源文件名
assetModuleFilename: "images/[hash:10][ext][query]",
// 在生成文件之前清空 output 目录
clean: true,
},
// 开发服务器配置
devServer: {
// 从目录提供静态文件
static: {
directory: path.join(__dirname, "public"),
publicPath: "/",
},
// 启动后打开浏览器
open: true,
// 监听请求的端口号
port: 8080,
},
// loader配置
module: {
rules: [
// 处理css文件
{
test: /\.css$/i,
use: [
// 创建style标签,将样式放入style标签中
// "style-loader",
// 提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
// postcss-preset-env 帮助postcss找到package.json中`browserslist`里边的配置
"postcss-preset-env",
],
],
},
},
},
],
},
// 处理less文件
{
test: /\.less$/i,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
],
],
},
},
},
"less-loader",
],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset",
},
// 处理html文件,加载其中的图片
{
test: /\.html$/i,
loader: "html-loader",
},
// 处理字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
// 模式
mode: "development",
// mode: 'production',
};
```
### 5.3、css压缩
webpack4使用 optimize-css-assets-webpack-plugin: [https://github.com/NMFR/optimize-css-assets-webpack-plugin](https://github.com/NMFR/optimize-css-assets-webpack-plugin)
webpack5使用 css-minimizer-webpack-plugin: [https://webpack.docschina.org/plugins/css-minimizer-webpack-plugin/](https://webpack.docschina.org/plugins/css-minimizer-webpack-plugin/)
```
npm install css-minimizer-webpack-plugin --save-dev
```
完整配置
```js
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// webpack配置
module.exports = {
// 入口文件
entry: "./src/index.js",
// 输出
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
// 自定义资源文件名
assetModuleFilename: "images/[hash:10][ext][query]",
// 在生成文件之前清空 output 目录
clean: true,
},
// 开发服务器配置
devServer: {
// 从目录提供静态文件
static: {
directory: path.join(__dirname, "public"),
publicPath: "/",
},
// 启动后打开浏览器
open: true,
// 监听请求的端口号
port: 8080,
},
// loader配置
module: {
rules: [
// 处理css文件
{
test: /\.css$/i,
use: [
// 创建style标签,将样式放入style标签中
// "style-loader",
// 提取js中的css成单独文件
MiniCssExtractPlugin.loader,
// 将css文件整合到js文件中
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [["postcss-preset-env"]],
},
},
},
],
},
// 处理less文件
{
test: /\.less$/i,
use: [
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [["postcss-preset-env"]],
},
},
},
"less-loader",
],
},
// 处理资源文件
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset",
},
// 处理html文件,加载其中的图片
{
test: /\.html$/i,
loader: "html-loader",
},
// 处理字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
],
},
// 插件配置
plugins: [
// 复制一份HTML文件,并自动引入打包资源(js/css)
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
optimization: {
// 开发环境下启用 CSS 优化
minimize: true,
minimizer: [
// 使用 cssnano 优化和压缩 CSS
new CssMinimizerPlugin(),
],
},
// 模式
mode: "development",
// mode: 'production',
};
```
https://www.bilibili.com/video/BV1e7411j7T5?p=15&spm_id_from=pageDriver