【前端工程化】Webpack入门(保姆级教程)
目录
一、概念
浏览器只认识普通的html、css、js文件,我们在前端开发过程中使用新特性、新语法写出的vue、jsx、ts等代码浏览器都是不认识的,所以就需要工具来把代码转换为浏览器认识的代码
Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(static module bundler),用于将项目中的各种资源,如JavaScript文件、图片、CSS样式表等,打包成一个或多个bundle(包)。Webpack使用的是js代码进行开发,基于Node平台运行
二、初始化项目结构
先用 npm init 创建package.json文件,然后再创建其他文件,如下:
webpack_demo/
┣ src/
┃ ┣ components/
┃ ┃ ┣ common.js
┃ ┃ ┗ util.js
┃ ┗ app.js
┣ index.html
┗ package.json
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>
<script src="./src/app.js"></script>
<body>
</body>
</html>
common.js文件和util.js文件的内容分别为:
export default function (...res) {
console.log("common模块", res);
}
export default function () {
console.log("util模块");
}
app.js文件内容为:
import common from './components/common.js';
import util from './components/util.js';
common(1,2,3)
util()
基于上面初始化出来的项目可以看到,index.html 中引入了 app.js,然后 app.js 中又引入了 common.js 和 util.js 文件,最后运行 index.html,应该会输出‘common模块123’和‘util模块’才对,但实际运行后的结果却是这样:

原因是浏览器不支持 import,那么就该 Webpack 登场了
三、安装webpack
使用下面命令安装webpack
npm i webpack webpack-cli -D
分别安装了 webpack 和 webpack-cli,webpack 是本体,而 webpack-cli 则是 webpack 的执行依赖, 能够命令式的执行 webpack。
安装好后,就可以使用 webpack 打包 src 下的 app.js 文件了,使之能够被浏览器使用
四、命令式使用webpack
使用下面命令使用webpack
npx webpack ./src/app.js
执行完毕后就打包成功了,但是我们发现会有一个Warning,大概意思是没有设置 mode,mode 可以指定打包的环境,这里在后面先加上 --mode=development(开发环境),正式环境和开发环境区分后面再介绍
npx webpack ./src/app.js --mode=development

这样就完全打包好了,命令式使用还有其他很多可以传递的参数,具体可看官方文档 :
五、配置式使用webpack
上面命令式的使用 webpack 需要手动的输入参数来告知 webpack 的打包环境,需要打包的文件等,这样每次打包都要输入很长的命令,非常麻烦。 所以 webpack 就提供了可以将参数配置化(大多数工具都是,方便使用),所以就需要在原有的基础上新增一个 webpack 的配置文件
webpack_demo/
┣ dist/ // 打包后生成的
┃ ┗ main.js
┣ src/
┃ ┣ components/
┃ ┃ ┣ common.js
┃ ┃ ┗ util.js
┃ ┗ app.js
┣ index.html
┣ package.json
┗ webpack.config.js
在项目根目录新增一个 webpack.config.js文件(配置文件可以为 json,这里为 js,比较灵活),里面内容为:
module.exports = {
entry: './src/app.js', // 需要打包的文件
mode: 'development' // 打包环境---开发环境
}
然后再使用 npx webpack --config ./webpack.config.js 执行即可:

--config 可以指定配置文件的位置,webpack 会找到相应的配置文件进行解析,从而打包。 所以就可以在 package.json 的 scripts 字段中配置脚本,就可快捷使用:
"scripts": {
"dev": "webpack --config ./webpack.config.js"
}
执行 npm run dev 即可(如果是pnpm则不用run,个人比较推荐pnpm,懂的都懂(* ̄3 ̄)╭)

上面两种方式打包后,都会在项目根目录生成一个 dist 文件夹,文件夹里会有一个 main.js 文件(这是默认行为,可以指定打包后的位置和文件名称),所以还需要在 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>
<script src="./dist/main.js"></script>
<body>
</body>
</html>
这样就打包好了,再次运行index.html就可以正常输出了

六、webpack具体配置
基本配置
entry:表示 webpack 的入口,指定打包的文件,可以一个或多个
output:表示输出文件的路径和文件名
mode:表示打包环境,可设置为 production(生产环境) 或 development (开发环境)
示例:
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
clean: true
},
mode: 'development'
}
上面配置会解析 src 下的 app.js 文件的相关依赖并打包,然后输出到当前项目的 dist 文件夹下,输出文件名为 main.js。
output 中的 clean 会在打包生成文件之前会按照这个字段的值进行清理行为,如果为 true,则清空 output 设定的目录下的文件。 mode为开发模式,开发模式可以编译 ES Module语法,而生产模式(production)则不仅可以编译 ES Module语法,还可以压缩代码。
看对比:


production 模式把代码压缩成了一行,并且优化了代码。
Loader
webpack 的 loader 主要用于对模块的转换,也就是对文件的转化,如将 less、sass 处理成 css,将图片处理成 data URL 等。
在使用之前先来看下 Loader 在配置中的格式:
module.exports = {
....
module: {
rules: []
}
}
先有一个 module 对象,其有一个 rules 字段,这个字段里边就是需要使用的 loader 了,如 css -loader:
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
// 其他写法
module: {
rules: [
{
test: /\.css$/,
loader: 'style-loader',
}
]
}
test 表示处理什么文件,用正则匹配,上面是只匹配后缀为 css 的文件,这样就只处理了 css 文件,而不会处理到其他文件;当使用的是 loader 字段时,则只可以传入一个 loader,而使用 use 字段,可以传入多个 loader; 如果使用了多个 loader,则 webpack 在使用 loader 的时候是从右到左(从下到上)执行的,如有 ['style-loader', 'css-loader'],执行顺序是先执行 css-loader,然后再执行 style-loader(css-loader的作用是将css编译为js,style-loader的作用是将编译后的css引入到html文件的style标签中)。
处理css文件
在 src 下创建 css 文件夹,然后新建一个 css 文件,里边写一些样式代码,在 index.html 中新增 div,使样式生效,然后在 app.js 中引入:
index.css的内容为:
.box1 {
width: 100px;
height: 100px;
background-color: red;
}
app.js 内的内容为:
import common from "./components/common";
import util from "./components/util";
import './css/index.css' // 新增的引入 css
common(1,2,3)
util()
index.html 的内容为:
....
<script src="./dist/main.js"></script>
<body>
<div class="box1"></div> <!-- 新增的div -->
</body>
....
文件创建完成后,开始打包css文件,安装loader:
pnpm i css-loader style-loader -D
安装后修改 webpack 的配置文件如下:
const path = require('path')
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
},
mode: 'production',
module: {
rules: [
// 新增的loader
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
}
修改后再次打包,即可成功打包并显示正确结果:

css-loader:css-loader 会处理 import / reuqire 引入的内容: 将 app.js 中的 import './css/index.css' 解析得到其样式代码
style-loader:style-loader 则将样式插入到 html 中: 将 css-loader 解析得到的样式代码插入到 html 中

所以,处理 CSS 资源,css-loader 和 style-loader 两者不可缺其一。
处理sass、less文件
和css类似,先创建less和sass样式文件,然后在app.js文件中引入,最后在html文件中创建对应的元素。处理css需要css-loader,那处理sass和less当然也需要对应的loader了,安装sass、less和对应的loader:
pnpm i less less-loader sass sass-loader -D
安装后在 webpack.config.js 中新增 loader:
module.exports = {
......
module: {
rules: [
.......
// 处理 less
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
// 处理 sass
{
test: /\.s[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
}
]
}
}
上面 less-loader 和 sass-loader 将 less/sass 文件处理成 css 文件,然后再由 css-loader 和 style loader 处理 css。(需要注意的是sass文件有sass和scss两种版本)
再次打包后可以看到结果:

处理图片
在项目中的 src 下新建 images 文件夹,并放入两张图片,在 index.css 中新增 CSS 代码,并在 index.html 中新增 div:
<div class="img1"></div>
<div class="img2"></div>
.img1 {
width: 200px;
height: 150px;
background-image: url('../images/1.jpg');
background-size: cover;
}
.img2 {
width: 200px;
height: 150px;
background-image: url('../images/2.jpg');
background-size: cover;
}
此时打包是打包不了的,需要配置相应的 loader,但是 webpack5 后不需要配置 loader,只要设置相应的资源类型即可
在 webpack.config.js 中新增 loader 配置如下:
{
test: /\.(jpe?g|png|gif|webp|svg|)$/,
type: 'asset',
parser: { // 图片资源处理
dataUrlCondition: {
maxSize: 200 * 1024 // 200kb以下的图片转为base64
}
},
generator: { // 图片资源输出路径
filename: 'static/images/[hash][ext][query]'
}
}
设定资源类型为 asset,并且通过 dataUrlCondition 设定小于 200kb 的图片转换成 base64,这里就会 将 2.jpg 转换成 base64 嵌入到 html 中,generator属性将把图片打包放到dist/static/images 目录下
[hash]: 表示hash值,后面可携带自定义位数,例如[hash:8]
[ext]:原文件扩展名
[query]:添加之前的query参数
重新打包后效果如下:


处理css兼容性
通过 loader,可以将一些较新的 CSS 语法能够在低版本浏览器中使用,而这个 loader 就是 postcss loader,但这个 loader 还依赖 postcss 和 postcss-preset-env,所以需要安装三个模块:
pnpm i postcss-loader postcss postcss-preset-env -D
postcss 是通过 JS 来转换样式,而 postcss-preset-env 则能够加强 CSS 的兼容性,所以 postcss-loader 依赖这两者,修改 webpack 的配置如下:

除了修改以上配置以外,在 package.json文件最外层属性新增:"browserslist": ["ie >= 7"]

然后在index.css文件中添加display:flex

再次打包后运行可以看到自动做了兼容性处理:

处理js兼容性
通过 loader ,还可以将 JS 语法在较低的浏览器版本中使用,主要就是通过 babel,同样需要安装三个模块,一个 loader,一个核心库,一个预设,分别就是 babel-loader、@babel/core、@babel/preset env:
pnpm i babel-loader @babel/core @babel/preset-env -D
安装后,在webpack.config.js中新增loader配置:
{
test: /\.js$/,
exclude: /node_modules/,
use: [
'babel-loader'
]
}
exclude属性用于排除指定文件
这样配置还不行,@babel/preset-env 才是主要转换代码的东西,为了后面方便修改,在项目根目录新建一个 babel.config.js 配置文件:
module.exports = {
presets: ['@babel/preset-env']
}
配置后,在 app.js 中写一些 ES6 语法,打包后就会转换成 ES5 的语法
在 app.js 中新增以下代码:
function count(...arg) {
console.log(arg[0] + arg[1])
}
count(1,2)

Plugin
webpack 的插件能够增强 webapck 的功能,本身 webpack 只是解析依赖从而打包,loader 使 webpack 能够转化文件,而 plugins 则使 webpack 能够拥有压缩,提取等更大强大的功能。 webpack 的插件主要在 plugins 字段上,是个数组,也就是可以使用多个插件,每个插件在使用的时候都必须传入一个 new 实例。
提取 CSS 为单独文件
上面通过 loader 处理 css 时,css 是通过 JS 直接插入到 html 中,不是用引入链接的方式,这样在访问 页面解析 JS 到解析完成会有一个突然出现的效果,影响体验。
通过 MiniCssExtractPlugin 插件可以将 CSS 提取到单独的文件中。
相关文档: MiniCssExtractPlugin | webpack 中文文档
安装这个插件:
pnpm i mini-css-extract-plugin -D
然后修改webpack.config.js文件



引入 mini-css-extract-plugin,然后在 plugins 中设置,最后将 style-loader 替换成 MiniCssExtractPlugin.loader。
打包后可以看到已经将css提取到单独的文件里了然后在html中引入这个文件


自动引入 JS 和 CSS
上面打包后,不管是 JS 还是 CSS 打包为单独文件时,在 index.html 中都需要手动引入相应的资源,如 果修改了 webpack 打包 JS 和 CSS 文件的路径,那么 index.html 也需要修改。 基于以上问题,可以通过 HtmlWebpackPlugin 插件解决。
相关文档:HtmlWebpackPlugin | webpack 中文文档
安装这个插件:
pnpm i html-webpack-plugin -D
然后修改webpack.config.js文件



先引入 html-webpack-plugin,然后将其添加到 plugins 中,同时将 index.html 中引入 css 和 js 的代码注释。
打包后,可看到在 dist 下有一个 index.html :

同时帮你自动引入了相关的资源,这时就可以访问这个新的 index.html 来查看效果了。
在配置 html-webpack-plugin 时,如果没有传入 template,生成的 index.html 的内容则是这样的: 我们自己写的一些 div 不见了,所以传入 template 的作用就是让 html-webpack-plugin 以一个 html 文件为模板去生成一个新的 html 文件
压缩 CSS
同样的,使用 CssMinimizerWebpackPlugin 这个插件能够将 CSS 压缩为一行,减少文件体积。
安装这个插件:
pnpm i css-minimizer-webpack-plugin -D
然后修改 webpack 配置:



还是一样的,引入 css-minimizer-webpack-plugin,然后在 plugins 中添加,最后修改 mode(css minimizer-webpack-plugin 默认在生产模式在才生效),打包后效果如下:

可以看到css已经被压缩成一堆看不懂的神秘代码了
自动清空打包目录
每次打包的时候,打包目录都会遗留上次打包的文件,为了保持打包目录的纯净,我们需要在打包前将 打包目录清空 这里我们可以使用插件 clean-webpack-plugin 来实现
安装这个插件:
pnpm i clean-webpack-plugin -D
修改webpack.config.js文件:


DevServer
devserver 可以在本地启动一个服务,使我们可以使用 http 协议去访问 index.html ,并且当修改代码时,能够监听当前项目的文件变动从而实现自动打包,而不用每次修改后都要手动打包:
在 webpack 配置中添加 devServe 字段,里边配置 host、port等。同时还需要安装 webpack-dev server 模块:
pnpm i webpack-dev-server -D

同时,package.json文件中webpack 打包命令也需要添加一个 serve 参数才能调用 webpack-dev-server:

启动 server 前,可以先将 dist 目录下的文件清空,然后再运行 pnpm dev,可以发现 dist 下并没有生成任何文件,这是因为server 打包后是放在内存中的,所以 dist 下也不需要任何文件,server 一般是在开发环境下使用的,如果在生产环境,就需要打包到本地dist文件了。
总结
本篇文章通过处理各种资源来介绍 webpack 的一些基础且常用的配置的使用,更多的 loader,plugins 等使用方法还是得到官方文档查询。
前端工程化是现代前端开发不可或缺的一部分,它帮助开发者创建可扩展、可维护且高性能的应用程序。随着前端技术栈的不断进步,工程化的最佳实践也在不断发展,以适应新工具和框架的出现。
更多推荐

所有评论(0)