前言
本篇是 webpack5 基础篇教程,意在用尽可能简介明了的描述,帮助初学者学习,二来给老手复习,三来自己巩固知识!话不多说,直接开干!
说明:
webpack:^5.75.0
webpack-cli:^5.0.1
1、基本配置
在开始使用 Webpack
之前,我们需要对 Webpack
的配置有一定的认识
1.1、webpack 5大核心
-
entry(入口)
entry
是 webpack 打包的入口,即指示 webpack 从哪里开始打包 -
ouput(出口)
output
是指示 webpack 将打包好的文件输出到哪里去,如何命名等 -
loader(加载器)
webpack 本身只能处理 js、json
,对于图片、字体等资源,webpack 需要借助 loader 进行解析 -
plugin(插件)
plugin
扩展 Webpack 的功能 -
mode(模式)
mode
指示 webpack 使用哪种模式,有两种development(开发模式)
production(生产模式)
2、项目初始化
2.1、安装 webpack
- 创建 learn_webpack5 文件夹,创建子文件夹 src,打开 vscode 终端,输入以下命令
npm init -y
npm i webpack webpack-cli -D
会生成如下文件:
- src 文件夹下创建 a.js、b.js、index.js 文件
//src/a.js
export function printA() {
console.log('a')
}
//src/b.js
export function printB() {
console.log('b')
}
//src/index.js
import { printA } from "./a";
import { printB } from "./b";
function print() {
printA()
printB()
}
print()
- 在根目录下,创建 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>
</body>
</html>
2.2、编写 webpack 基本配置
在根目录下,创建webpack/webpack.common.js,并编写如下基本配置:
//webpack/webpack.common.js
const path = require('path')
module.exports = {
//打包的入口配置
//相对路径和绝对路径都行
entry: path.resolve(__dirname, "../src/index.js"),
//打包文件的出口配置
output: {
// path: 文件输出目录,必须是绝对路径
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, '../dist'),
//输出的文件名
filename: 'bundle.js',
//webpack5 版本中,自动清除上一次打包的结果
clean: true
},
//加载器配置
module: {
rules: [
]
},
//插件配置
plugins: [],
//模式配置
mode: 'development'
}
2.3、配置 package.json 脚本命令
打开 package.json,添加下面的命令:
"scripts": {
"build": "webpack --config ./webpack/webpack.common.js",
},
在 vscode 终端运行 npm run build,整体目录如下:
3、处理 HTML 资源
html-webpack-plugin
会生成一个HTML5文件,在 body 中使用 scrip t标签引 webpack 生成的 bundle.js
(1)下载 html-webpack-plugin
npm i html-webpack-plugin -D
(2)在 plugins 中配置 html-webpack-plugin
const HtmlWebpackPlugin = require
module.exports = {
//前面的代码...
plugins: [
new HtmlWebpackPlugin({
//输出的路径
template: path.resolve(__dirname, '../public/index.html'),
//输出的文件名
filename: 'index.html'
})
]
}
(3)再次执行 npm run build
(4)打开 dist/index.html,右键,选择运行在浏览器中:
f12 打开 network,发现我们打包后的资源都下载下来了
打开控制台,发现打印了 a b
这样我们打包后的 bundle.js 就可以直观的运行在页面上了。
4、处理样式资源
本章节我们学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl
样式资源
Webpack 本身是不能识别样式资源的
,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
4.1、处理 CSS 样式
(1)下载 css-loader、style-loader
npm i css-loader style-loader -D
- css-loader:帮助 webpack 解析 css,包括 @import 和 url()
- style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
(2)配置
// webpack/webpack.common.js
module.exports = {
//前面的代码...
module: {
rules: [
{
test: /\.css$/, //匹配以 css 结尾的文件
use: ["style-loader", "css-loader"], //从右向左解析
},
]
},
//后面的代码...
}
(3)创建 src/styles/a.css,写入样式
body{
background-color: aqua;
}
在 src/index.js 中引入 a.css
import './styles/a.css'
(4)执行 npm run build 后,重新在浏览器运行 dist/index.html,发现样式已经生效
4.2、处理 Less 样式
(1)下载 less-loader
npm i less-loader -D
- less-loader:负责将 Less 文件编译成 Css 文件
(2)配置
// webpack/webpack.common.js
module.exports = {
//前面的代码...
module: {
rules: [
{
test: /\.css$/, //匹配以 css 结尾的文件
use: ["style-loader", "css-loader"], //从右向左解析
},
{
test: /\.less$/, //匹配以 less 结尾的文件
use: ["style-loader", "css-loader", "less-loader"], //从右向左解析
},
]
},
//后面的代码...
}
(3)创建 src/styles/b.less,写入样式
div{
width: 200px;
height: 200px;
background-color: red;
span{
color: white;
}
}
(4)打开 public/index.html,添加一个 div 和 span
<!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>
<div>
<span> 123 </span>
</div>
</body>
</html>
(5)打开 src/index.js,引入 b.less
import './styles/b.less';
(6)执行 npm run build 后,页面如下:
4.3、处理 Sass、Scss 样式
(1)下载 sass-loader、sass
npm i sass-loader sass -D
(2)配置
// webpack/webpack.common.js
module.exports = {
//前面的代码...
module: {
rules: [
{
test: /\.css$/, //匹配以 css 结尾的文件
use: ["style-loader", "css-loader"], //从右向左解析
},
{
test: /\.less$/, //匹配以 less 结尾的文件
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /.s[ac]ss$/,//匹配以 sass、scss 结尾的文件
use: ["style-loader", "css-loader", "sass-loader"],
},
]
},
//后面的代码...
}
(3)创建 src/styles/c.scss,写入样式:
$blue: blue;
.box2{
width: 300px;
height: 300px;
background-color: $blue;
}
(4)打开 public/index.html,添加一个 div.box2
<!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>
<div>
<span> 123 </span>
</div>
<div class="box2"></div>
</body>
</html>
(5)打开 src/index.js,引入 c.scss
import './styles/c.scss';
(6)执行 npm run build,页面如下:
4.4、抽取 CSS 到单独的文件
我们发现上面的打包结果,head 标签中有 3 个 style 标签,如果在 src/index.js 里面引入的样式资源越多,则打包后的 style 标签就越多,这个时候我们希望把所有的 CSS 都提取到一个单独的文件中,减少 DOM 的操作,我们需要使用 mini-css-extract-plugin
(1)下载 mini-css-extract-plugin
npm i mini-css-extract-plugin -D
(2)配置
// webpack/webpack.common.js
module.exports = {
//前面的代码...
module: {
rules: [
{
test: /\.css$/,
//将 style-loader 换成 MiniCssExtractPlugin.loader
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.less$/, //匹配以 less 结尾的文件
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
]
},
plugins: [
//前面的代码...
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "asset/css/main.css",
}),
]
}
(3)执行 npm run build
(4)页面运行结果如下:
4.5、兼容性处理
某些样式可能并不兼容低版本浏览器,所以需要对 css 进行兼容性处理
(1)下载 postcss-loader postcss postcss-preset-env
npm i postcss-loader postcss postcss-preset-env -D
(2)配置
// 由于需要对 css、less、sass 都进行兼容性处理,所以我们先合并一下样式的配置
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
//在 css-loader 后,配置 postcss-loader
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
{
test: /.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
}
]
}
}
(3)在 package.json 新增 browserslist 配置
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
(4)在 src/styles/b.less 中添加样式
div{
width: 200px;
height: 200px;
background-color: red;
span{
color: white;
transform: rotate(45deg); /* 这个属性会产生浏览器内核前缀如 -webkit*/
}
}
(5)执行 npm run build,查看 dist/assets/css/main.cs
4.6、压缩 CSS
打包后的文件体积越小,浏览器加载资源的速度就越快,当项目很大时,压缩文件体积是非常有必要的,接下来我们压缩打包后 CSS 文件的体积
(1)下载 css-minimizer-webpack-plugin
npm i css-minimizer-webpack-plugin -D
(2)配置
//webpack/webpack.common.js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
//前面的代码...
plugins: [
// css压缩
new CssMinimizerPlugin(),
]
}
(3)执行 npm run build,发现 dist/assets/css/main.css 的代码被压缩了
5、处理图片资源
过去在 Webpack4 时,我们处理图片资源通过 file-loader
和 url-loader
进行处理
现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源
(1)配置
module.exports = {
module: {
rules: [
//前面的代码
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
// 小于10kb的图片会被base64处理
// 优点:减少请求数量
// 缺点:体积更大
maxSize: 10 * 1024
}
},
generator: {
// 将图片文件输出到 asset/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "asset/imgs/[hash:8][ext][query]",
},
},
]
}
}
(2)添加图片 创建 src/assets/img 文件夹,在该文件夹下添加三张图片(素材自己随便找)
如下:
(3)使用图片 首先,我们先在 src/public/index.html 中添加两个 div
然后,在 src/styles/b.less 中,写入下面的样式:
div{
width: 200px;
height: 200px;
}
.box2{
background-image: url("../asset/img/1.jpeg");
background-size: cover;
}
.box3{
background-image: url("../asset/img/2.png");
background-size: cover;
}
.box4{
background-image: url("../asset/img/3.gif");
background-size: cover;
}
最后,执行打包命令 npm run build
,观察结果
首先,图片资源被打包到了 dist/asset/imgs
目录中,并且只有两张图片,分别是 2.png 和 3.gif
打包后的输出
而 1.jpeg 没有,是因为 1.jpeg 小于10kb的图片,所以被处理为了 base64 格式 打开页面,我们发现
至此,我们完成了对图片资源的处理。
6、处理字体图标资源
子图图标资源的处理和图片资源的处理方式类似,这里直接上配置,不再赘述
(1)配置
module.exports = {
module: {
rules: [
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
// 将字体图标文件输出到 asset/fonts 目录中
// 将字体图标命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "asset/fonts/[hash:8][ext][query]",
},
},
]
}
}
(2)在阿里巴巴矢量库,选择想要的图标添加到购物车,统一下载到本地(不会的同学可以百度,这里不过多赘述)
(3)将 iconfont.ttf、 iconfont.woff、 iconfont.woff2
添加到 src/asset/fonts, 将 iconfont.css
添加到 src/asset/styles
(4)使用字体图标,在 src/index.js 中引入字体图标
//src/index.js
import './styles/iconfont.css'
(5)在 src/public/index.html 中,使用字体图标
<i class="iconfont icon-yulan"></i>
<i class="iconfont icon-tiaozheng"></i>
(6)执行 npm run build
,打开页面
至此,图标字体资源的处理完毕
7、处理其他资源
开发中可能还存在一些其他资源,如音视频等,我们也一起处理了
module.exports = {
module: {
rules: [
{
test: /\.(map4|map3|avi)$/,
type: "asset/resource",
generator: {
filename: "asset/media/[hash:8][ext][query]",
},
},
]
}
}
8、处理 JS 资源
Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法,导致 js 不能在 IE 等浏览器运行,所以我们希望做一些兼容性处理,我们使用 Babel 来完成
(1)下载相关的包
npm i @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime -D
其中:
@babel/core
:babel核心库
babel-loader
:处理 JS 的插件
@babel/preset-env
:将 ES6 向后兼容
@babel/plugin-transform-runtime
:处理 async,await、import() 等语法关键字的帮助函数
(2)根目录下,创建 babel.config.js 文件
module.exports = {
presets: ["@babel/preset-env"],
};
(3)webpack.common.js中配置
module.exports = {
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
]
}
}
(4)在 src/public/index.html 中
<button>使用 es6 箭头函数</button>
<script>
document.querySelector('button').onclick = () => {
console.log('使用 es6 箭头函数')
}
</script>
(5)执行 npm run build
,打开页面,点击按钮后,窗口控制台的输出结果
9、区分环境
实际开发中,我们一般将 webpack 配置分为 webpack.common.js(公共配置)、webpack.config.dev.js (开发环境) 和 webpack.config.prod.js (生产环境)
,将配置的代码合并,避免重复代码
(1)npm i webpack-merge -D
(2)创建 src/webpack/webpack.config.dev.js
和 src/webpack/webpack.config.prod.js
,并分别对不同环境进行配置
- 开发环境 webpack.config.dev.js
(1)npm i webpack-dev-server -D
(2)配置
const path = require("path");
module.exports = {
mode: "development",
devServer: {
hot: true, //热更新
open: true, //编译完自动打开浏览器
compress: true, //开启gzip压缩
port: 3000, //开启端口号
//托管的静态资源文件
//可通过数组的方式托管多个静态资源文件
static: {
directory: path.join(__dirname, "../public"),
},
},
};
- 生产环境 webpack.config.prod.js
module.exports = {
mode: "production",
output: {
clean: true
}
};
(3)打开 package.json,写下命令
{
//...其他代码
"scripts": {
"build": "webpack --config ./webpack/webpack.common.js --env production",
"serve": "webpack serve --config ./webpack/webpack.common.js --env development"
},
}
(4)修改 src/webpack/webpack.common.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");
//合并配置的插件
const { merge } = require("webpack-merge");
//引入生产环境和开发环境的配置
const prodConfig = require("./webpack.config.prod");
const devConfig = require("./webpack.config.dev");
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
//在 css-loader 后,配置 postcss-loader
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
const commonConfig = {
//打包的入口配置
//相对路径和绝对路径都行
entry: path.resolve(__dirname, "../src/index.js"),
//打包文件的出口配置
output: {
// path: 文件输出目录,必须是绝对路径
// path.resolve()方法返回一个绝对路径
// __dirname 当前文件的文件夹绝对路径
path: path.resolve(__dirname, '../dist'),
//输出的文件名
filename: 'bundle.js',
},
//加载器配置
module: {
rules: [
{
test: /\.css$/,
use: getStyleLoaders(),
},
{
test: /\.less$/, //匹配以 less 结尾的文件
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
// 小于10kb的图片会被base64处理
// 优点:减少请求数量
// 缺点:体积更大
maxSize: 10 * 1024
}
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "asset/imgs/[hash:8][ext][query]",
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "asset/fonts/[hash:8][ext][query]",
},
},
{
test: /(\.jsx|\.js)$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
]
},
//插件配置
plugins: [
new HtmlWebpackPlugin({
//输出的路径
template: path.resolve(__dirname, '../public/index.html'),
//输出的文件名
filename: 'index.html'
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "asset/css/main.css",
}),
// css压缩
new CssMinimizerPlugin(),
],
}
module.exports = function(env) {
//env.production 用于获取 终端命令行中
const isProduction = env.production;
process.env.NODE_ENV = isProduction ? "production": "development";
const config = isProduction ? prodConfig : devConfig;
const mergeConfig = merge(commonConfig, config);
return mergeConfig;
};
(5)运行 npm run serve
查看开发环境
打开 localhost:3000
此时,我们去更改 src/a.js 中的输出,然后保存
//src/a.js
export function printA() {
console.log('aaaaaaaa')
}
发现页面进行了热更新
至此,webpack 的环境分离已经完成
结尾
以上就是 webpack5 基础配置的教程,希望能帮助初学者学习,以及老手巩固基础
如果 这篇文章 对你有帮助,欢迎 点赞、收藏、评论,如果有 错误或还有疑问的地方,请 评论留言或者私信!