安装 webpack
npm i webpack webpack-cli -D
webbpack 配置文件
webpack 默认会使用当前文件夹下 src/index.js 做为打包的入口文件,当前文件夹下的webpack.config.js 作为 webpack 的配置文件,如果想要使用其他配置文件时,可以再 package.json 中增加一个新的脚本:
{"script": "webpack --config 配置文件地址"}
如果 webpack 安装在了全局可以只使用 webpack --config 地址 的形式去运行 webpack 并指定配置文件地址,但如果 webpack 是安装在项目中时,如果想在命令行中执行 webpack ,则需要在先找到 node_modules 中的 webpack 再执行,但如果使用上面 script 脚本的方式则不需要指定 webpack 地址,直接在命令行 npm run build 即可。
webpack 基本配置
webpack 是运行在 node 环境中的,所以在配置文件中我们需要使用 commonjs 方式将配置项导出。
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js', // 入口
output: {
filename: 'main.js', // 打包出来的文件名称
path: path.resolve(__dirname, './dist'), // 指定打包出来的文件存储路径
// 如果打包一个库文件会用到以下配置
libraryTraget: 'umd', // 打包为 umd 模块
library: 'ki', // 库的名称,也是全局暴露出来的变量名
globalObject: "this", // 全局变量挂载到哪里,默认为 self
},
};
- entry:入口文件,webpack 会根据这个入口文件,分析其依赖关系进行打包
- output:出口配置,打包完后对应的配置
- filename:指定打包出来的 js 文件名称
- path:指定打包出来的文件存放位置
webpack 依赖图
webpack 在处理应用程序时,它会根据命令或者配置文件找到入口文件,从入口文件开始,分析依赖生成一个 依赖关系图 ,这个依赖关系图会包含应用程序中所需的所有模块(js文件、图片、css、html),然后遍历图结构,打包一个个模块(使用不同的 loader 处理):
loader 介绍
webpack 默认只能解析 JS 文件和 JSON 文件,如果想要解析其他文件(CSS、图片、字体等)就需要配合对应的 loader 来实现: ```javascript module.exports = { … module: { rules: [ {
use: [test: /\.css$/, // 一个正则表达式,匹配对应的文件,匹配中的文件将会使用下面的 loader 处理
], }, ], }, }// 使用多个 loader { loader: 'css-loader', // loader 名称 options: { // 传递给 loader 的配置 }, },
// 如果只使用了一个文件那么在 rules 数组中可以这样简写: { test: ‘test’, loader: ‘loader name’, // 去掉 use 直接使用 loader }
// 如果不需要给 loader 传递 option 时, 可以直接在 user 中写 loader 名称字符串 { test: ‘test’, use: [ ‘loader name1’, ‘loader name2’, ], }
当配置多个 loader 时,loader 的执行顺序时从后往前、从下往上、从右往做的,先执行 use 数组后面的 loader,再指定前面的 loader。
<a name="pq1Hd"></a>
## 打包 CSS、LESS 文件
打包 CSS 文件和 LESS 文件需要用到下面几个 loader:
```javascript
npm i css-loader style-loader less-loader less;
css-loader 用于解析 css 文件,style-loader 用于将解析好的 css 插入到 html 的 header 中,less-loader 用于调用 less 工具处理 less 文件,将 less 文件转为 css 文件,webpack 配置如下:
const path = require('path');
module.exports = {
entry: './src/index.js',
module: {
rules: [
// 配置解析 css 文件的 loader
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
],
},
// 配置解析 less 文件的 loader
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
},
],
},
],
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, './disy'),
},
};
浏览器兼容性
在开发中会遇到浏览器的兼容性问题,比如不同浏览器对与的 CSS 特性的支持,在一些旧版本的浏览器中我们需要加一些前缀来让其支持对应的 CSS 特性,这时我们就会用到 babel、postcss 等工具来进行浏览器的兼容,但是浏览器非常多且又很多版本,到底哪些浏览器和版本需要兼容呢?可能需要考虑到浏览器的市场占用率来判断到底需不需要兼容他们。
浏览器市场占有率查询网站:https://caniuse.com/usage-table
browserslist 工具
browserslist 是一个在不同前端工具中(babel、postcss等),共享目标浏览器和 Node.js 版本的配置。
通过安装 browserslist 工具,编写配置文件,如 babel、postcss 等前端工具,都会自动的找到这个配置文件,通过这个配置文件来实现对应浏览器的兼容性处理。
注:在安装 webpack 时已经安装上了 browserslist 工具,我们直接编写配置文件即可。
browserslist 配置文件
对于 browserslist 配置可以写在两个地方:
- 创建
browserslistrc文件编写配置信息 - 在
package.json中编写 browserslist 配置信息


配置文件基本编写规则:
- defaults:Browserslist的默认浏览器(> 0.5%, last 2 versions, Firefox ESR, not dead)。
- 5%:通过全局使用情况统计信息选择的浏览器版本。 >=,<和<=工作过。
- dead:24个月内没有官方支持或更新的浏览器。现在是IE 10,IE_Mob 11,BlackBerry 10,BlackBerry 7, Samsung 4和OperaMobile 12.1。
- last 2 versions:每个浏览器的最后2个版本。
- last 2 Chrome versions:最近2个版本的Chrome浏览器。
- last 2 major versions或last 2 iOS major versions:最近2个主要版本的所有次要/补丁版本。
- not ie <= 8:排除先前查询选择的浏览器。
如果没有配置文件,那么会应用一个默认规则:
> 0.5%
last 2 versions
Firefox ESR
not dead
PostCSS 工具,处理 CSS 兼容问题
Post CSS 是一个通过 JavaScript 来转换样式的工具,这个工具可以帮我们实现一些 CSS 的转换和适配,比如添加浏览器前缀、CSS 样式重置,但是实现这个功能还需要再安装一些 Post CSS 插件,比如 autoprefixer。
在 webpack 中使用时我们可以安装以下依赖:
npm i postcss postcss-loader postcss-preset-env -D
postcss-preset-env: 就是一个 postcss 的插件,用于处理 css 的兼容问题。
修改 webpack 配置:
module.exports = {
...
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
// 因为 postcss-loader 是对 css 文件做处理的,所以要写在 less-loader 的上面
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env'), // 引入 postcss-preset-env 插件
],
},
},
},
'less-loader',
],
}
],
},
};
postcss 的配置也可以写在一个单独的 postcss.config.js 文件中,这时在 webpack 配置中就不需要写 postcss-loader 的 option 了。
// 根目录下创建 postcss.config.js 文件
module.exports = {
plugins: [
require('postcss-preset-env'),
],
}
// webpack 中:
use: [
...
'postcss-loader',
'less-loader',
]
打包图片资源
打包图片时可以使用 file-loader 或者 url-loader,这个两个 loader 之间的区别是 url-loader 可以将图片转为 base64 之间嵌入在代码中,使用方式如下:
npm i file-loader url-loader -D
webpack 配置:
module.exports = {
module: {
rules: [
{
test: /\.(jpe?g|png|gif)$/,
use: [
// file-loader 配置
{
loader: 'file-loader',
name: 'images/[name]-[hash:8].[ext]', // 指定输出文件名称和路径
},
// or
// url-loader 配置
{
loader: 'url-loader',
options: {
// 小于 8kb 就转为 base64 打包到 js 文件中, 大于 8kb 的打包到指定的文件夹中
limit: 8 * 1024,
name: 'images/[name]-[hash:8].[ext]', // 指定输出文件名称和路径
},
},
],
},
],
},
};
文件名称规则
在上面的代码中指定图片名称时用了 [name]-[hash:8].[ext] 这种写法,这种写法是 webpack 的 placeholder 写法,常用的 placeholder 如下:
- [ext]:文件拓展名
- [name]:原文件名称
- [hash]:文件内容通过 MD4 散列函数生成的散列值
- [hash:x]:保留 x 位 hash 值,比如 [hash:8] 就是保留前 8 位 hash值
- [path]:webpack 配置文件路径
- [content-path]:在这里和 hash 相同,在其他地方不同,可以用于做性能优化。
asset module type
在 webpack 5 之前可以使用上面的 url-loader、file-loader 处理文件资源,在 webpack5 中就不再需要这两个 loader 了,可以使用 asset module type 实现相同的功能。
资源模块类型
asset module type 支持以下几种类型配置:
- asset/resource: 打包发送一个文件资源,类似 file-loader
- asset/inline : 将文件资源转为 data URI,类似 url-loader
asset : 在单独打包和转为 data URI 之间自动选择,类似 url-loader
使用 asset module type
module.exports = { module: { rules: [ { test: /\.(png|jpe?g)/, type: 'asset/resource', // 指定 asset module type }, ], }, }指定打包文件名称和目录:
有两种方式可以指定 asset module type 打包出来的文件名称和存放目录:在出口 output 中指定
assetModuleFilename字段,这样可以指定全局的 asset module type 存放方式。- 在单个 rule 中配置,这样只有匹配到的文件才会这样处理
注:[ext] 占位符在这里默认有了 “.” ,类如 .png,所以就不需要自己加 “.” 了。
// 第一种方式(全局设置) output:
module.exports = {
output: {
...,
assetsModuleFilename: '[name]-[hash:8][ext]',
},
...
}
// 第二种方式(单个设置):
module.exports = {
module: {
rules: [
{
test: /\.png$/,
type: 'asset',
generator: {
filename: '[name]-[hash:8][ext]',
},
},
],
},
}
使用 type = asset 实现 url-loader
module.exports = {
module: {
rules: [
{
test: /\.png$/,
type: 'asset',
parser: {
dataUrlCondition: {
// 配置最大 size,小于这个 size 就会转为 base64
maxSize: 10 * 1024,
},
},
generator: {
// 指定打包文件名称和目录
filename: 'imgs/[name]-[hash:8][ext]',
},
},
],
},
};
Plugin
Loader 是用于处理特定的模块类型转换,而 Plugins 是用于执行更加广泛的任务,比如:打包优化、资源管理、变量环境注入等。
Plugins 的配置
plugin 配置在 plugins 字段中,每个 plugin 都是一个类,所以需要通过 new 调用。
module.exports = {
plugins: [
// .. 多个 plugin
],
}
CleanWebpackPlugin
每次执行打包时都会创建一个文件夹,里面放着打包好的资源,多次打包时同名资源会被覆盖,没有出现重名的资源不会被覆盖和删除,如果我们不需要某些资源时,需要手动删除,这时可以利用 CleanWebpackPlugin 插件,在打包之前先将之前打包的文件删除掉,这样就不需要手动删除了:
npm i clean-webpack-plugin -D
配置:
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(),
],
}
HtmlWebpackPlugin
HtmlWebpackPlugin 可以自动生成一个 html 模板、或指定一个 html 模块,在打包后将打包完成的资源,如 JS 文件,自动引入到这个 html 模板中:
npm i html-webpack-plugin -D
配置:
const HtmlWepbackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWepbackPlugin({
template: 'public/index.html', // 自己指定模板,如果不指定会自动创建
title: 'hello webpack', // 传递一个配置,可以在模板中指定,打包后后替换掉
inject: 'body', // 代码的插入位置,默认为 heade
cache: true, // 开启缓存,如果文件没有发生改变就不会生成新的文件
minify: {
removeComments: true, // 移除注释
collapseWhirespace: true, // 折叠空格
},
}),
],
};
模板:
<html>
<helder>
<title>
/*这里会接受到配置中传递的 title */
<%= htmlWepackPlugin.options.title %/>
</title>
</helder>
<body>
<div id='app'></div>
</body>
</html>
DefinePlugin

上图 Vue 的模板中有一个 BASE_URL 的属性,这个并不是 html-webpack-plugin 配置的,而是全局的 webpack 配置属性,它可以在任何地方使用,配置这些全局属性的方式就是 definPlugin,definePlugin 已经集成在了 webpack 中,不需要单独下载,之间引入使用即可:
const { DefinePlugin } = require('webpack');
module.exports = {
plugins: [
new DefinePlugin({
BASE_URL: '"/"', // 注意在这里写字符串时需要写两个引号
}),
],
};
CopyWebpackPlugin
有的文件不需要额外的处理直接复制到打包好的文件中即可,这时可以使用 copy-webpack-plugin 实现:
npm i copy-webpack-plugin -D
配置:
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
// 注意: 指定的文件目录中必须存在内容(排除掉忽略文件后存在内容), 不然打包会报错
{
from: 'public', // 需要打包处理的文件目录
// to: 'dist', // 指定复制文件到哪个地方, 可以不指定, 默认跟随 webpack 的出口
globOptions: {
// 指定忽略复制的文件
ignore: [
'**/index.html',
],
},
},
],
}),
],
};
