1. 开发环境和生产环境的定义
webpack 对开发和生产环境的定义很清楚。webpack 在配置对象中提供了一个 mode 参数
mode:production/development 两个结果
production: 代表生产环境,当配置为此结果时,webpack 会对所有的js和html进行压缩处理,并且将构建结果输出到指定文件结构。用于发布到生产服务器。
development: 代表开发环境,当配置为此结果时,webpack 要配合 webpack-dev-server插件来使用,此时会启动本地服务器,用来调试和开发前端项目的代码,还需要配合 devtools 来实现编译代码和开发代码的映射来保证调试的准确性。
2. 手动简单配置一个 webpack 打包项目
2.1 初始化文件夹
npm initnpm init -y -- 快速生成默认配置-- 初始化时的配置项package name: (demo1) -- 自动识别的包名version: (1.0.0) -- 版本号description: webpack cli test -- 描述entry point: (index.js) -- 入口点,也就是作为依赖包给别人使用时,import 导入的默认文件test command: -- 测试命令git repository: -- git仓库地址keywords: webpack demo -- 关键字:可作为发布到 npm 仓库搜索的关键字author: Ahcheng -- 作者license: (ISC) -- 软件许可证
生成 package.js 文件
{"name": "demo1","version": "1.0.0","description": "webpack cli test","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": ["webpack"],"author": "Ahcheng","license": "ISC"}
2.2 安装 webpack 和 webpack 脚手架
npm i webpack webpack-cli -D
package.json 文件中会自动添加开发依赖项
..."license": "ISC","devDependencies": {"webpack": "^5.69.1","webpack-cli": "^4.9.2"}
2.3 新建 webpack 配置文件和资源文件
三个配置文件:
webpack.base.js他代表webpack中公用部分的配置信息webpack.dev.js他代表开发环境的配置文件部分,dev代表 developmentwebpack.prod.js他代表生产环境的配置文件部分,prod代表 production
两个资源文件夹和文件
- public 文件夹,存放公共资源,比如 index.html
- src 文件夹,存放源代码,比如 index.js
2.4 下载 webpack 插件 html-webpack-pulgin 打包 HTML 文件
npm i html-webpack-pulgin -D
插件都是 npm 包,插件的具体使用可以去 npmjs 查看使用说明
2.5 通过配置文件配置 webpack
const HtmlWebpackPlugin = require('html-webpack-plugin') // 导入 html-webpack-plugin 插件const path = require('path') // 导入 node.js 中 path 模块// webpack 是运行在 node.js 环境中的程序,所以得使用 CommonJs 模块语法module.exports = {// 入口:要打包哪些文件entry: {index: './src/index.js',index1: './src/index1.js'},// 出口:打包输出到哪里去output: {path: path.resolve(__dirname,'dist'), // 输出路径filename: '[name].bundle.js', // 生成的文件名,因为输入文件可能不止一个,[name]为获取输入文件的引用名动态拼接成输出的文件名// 公共路径,表示:dist中模板文件中自动引入js和css文件时在最前面拼的一部分字符串,如:<script src="publicPath/main.bundle.js"></script>publicPath: '',},// 配置插件,数组形式plugins: [// 打包 HTML 文件的插件,webpack 默认只能打包 js 文件new HtmlWebpackPlugin({template: './public/index.html', // html 模板的位置filename: 'index.html', // 生成的文件名,打包输出 HTML 到达的位置就是打包 js 的 output 位置chunks: ['index','index1'], // 打包输出的 index.htm1 中会自动引入 chunks 组件,该组件能把 js 文件自动引入 HTML 文件中。这里设置的是 entry 中定义的 key}),]}
publicPath 详解
2.6 在 package.json 文件中设置脚本,启动 webpack 服务进行打包构建
// webpack 指定脚本启动 webpack 服务// --config 指定配置文件,默认配置文件为 webpack.config.js// --color 日志启用颜色// --progress 输出构建的过程"scripts": {"webpack_serve": "webpack --config webpack.base.js --color --progress ",},// npm run webpack_serve
打包构建好后,js 原文件按出口原则生成了新的 js 文件,且新构建好的 js 文件被自动引入 HTML。这样就基本完成了一个 webpack 构建过程的配置。
![]() |
![]() |
|---|---|
但实际开发的时候存在多个构建环境,开发、测试、生产等等,且各个环境配置各不相同,我们也不会手动去打开模板文件查看运行结果。针对多个环境我们可以模块化配置文件来处理。
2.7 配置文件的解耦合 webpack-merge
模块化 webpack 的配置需要一个插件webpack-merge来合并基础配置文件和环境配置文件。
npm i webpack-merge -D
基础配置文件沿用上文的 webpack.base.js。配置开发环境的配置文件 webpack.dev.js
const { merge } = require('webpack-merge') // webpack-merge 导出的对象不止一个,要解构赋值const base = require('./webpack.base.js') // 引入基础配置文件// merge() 合并两个配置文件,若有重复内容,后面文件的内容会覆盖前面文件的内容module.exports = merge(base, {// 这个 { mode: development} 就是这个开发配置文件的内容mode: 'development'})
注意:现在合并后的配置文件是由 webpack.dev.js 导出的,所以要去 package.json 修改一下 webpack 的启动配置文件。
// 直接添加一条脚本命令"scripts": {"webpack-serve": "webpack --config webpack.base.js --color --progress ","webpack-dev": "webpack --config webpack.dev.js --color --progress", // 开发环境构建脚本"test": "echo \"Error: no test specified\" && exit 1"},// npm run webpack-dev 启动脚本构建开发环境的包
2.8 自动打包构建 webpack-dev-server
为了方便调试,将 webpack 与提供实时重装的开发服务器结合使用。webpack-dev-server 仅用于开发。它在后台使用 webpack-dev-middleware,监听源代码的变动自动打包构建输出到内存中,以提供快速访问。
npm install webpack-dev-server -D
webpack-dev-server 服务启动脚本
"scripts": {"dev": "webpack serve --config webpack.dev.js --hot" //npm 脚本,npm run dev 执行}// --hot 开启热更新
注意:凡是修改了 webpack 配置文件,或修改了 package.json 配置文件,必须重启实时打包的服务器,否则最新的配置文件无法生效!
在 webpack 配置文件中,可以通过 devServer 节点对 webpack-dev-server 插件进行更多的配置
比如和 Tomcat 一样自动启动浏览器打开项目,不用手动去输入 localhost:8080
webpack.dev.js
const { merge } = require('webpack-merge') // webpack-merge 导出的对象不止一个,要解构赋值const base = require('./webpack.base.js') // 引入基础配置文件const path = require('path')module.exports = merge(base, {mode: 'development',// 配置本地服务devServer: {// //配置本地的静态资源文件夹,用来让这两个文件夹内部的文件可以通过访问 http 地址直接展示static: [path.resolve(__dirname,'dist'), // 目标构建出的路径path.resolve(__dirname,'public') // 入口 public 的路径],open: true, //初次打包完成,自动打开浏览器host: '127.0.0.1', //实时打包的主机地址port: 8080 //实时打包的端口号,80端口是网址唯一可以省略不写的端口号}})
2.9 清除打包的缓存 clean-webpack-plugin
clean-webpack-plugin 用来清理 dist 文件夹,每次执行构建的时候清空上次构建的结果防止文件缓存
安装 clean-webpack-plugin
npm i clean-webpack-plugin -D
配置 webpack.prod.js
- hash 在迭代开发的时候避免了重名,这样浏览器就不会从缓存加载老文件给到用户,而是重新加载最新的包 ```javascript const base = require(‘./webpack.base.js’) const { merge } = require(‘webpack-merge’) // 解构赋值 const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)
module.exports = merge(base, { // 定义为生产环境 mode: ‘production’, // 重新配置输出,会覆盖 base 中的输出配置 output: { // 指定输出文件名格式,name 会读取 entry 中的 key,hash 给每个生成的文件打上唯一标志 filename: ‘[name] - [hash].js’ }, plugins: [ // 清理dist文件夹的插件,用来在每次执行构建的时候清空上次构建的结果防止文件缓存 new CleanWebpackPlugin() // 新建插件实例,相当于开启插件 ] })
启动脚本:生产环境打包肯定要打包到磁盘```javascript"scripts": {"build": "webpack --config webpack.prod.js --color --progress",},
3. 加载器 loader
loader 概述
在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。其他非 .js 后缀名结尾的模块
webpack 默认处理不了,需要调用 loader 加载器才可以正常打包,否则会报错!
loader 加载器的作用:协助 webpack 打包处理特定的文件模块。
比如:
- css-loader 可以打包处理 .css 相关的文件
- less-loader 可以打包处理 .less 相关的文件
- babel-loader 可以打包处理 webpack 无法处理的高级 JS 语法
loader 的调用过程

babel
安装 babel-loader
- loader 都是加载机,用于给 webpack 增加能力
安装 babel 核心库 ```javascript npm i @babel/core -D npm i @babel/preset-env -D npm i core-js -Snpm i babel-loader -D
//或者 npm i @babel/core @babel/preset-env -D npm i core-js -S
core-js 是一个 babel 用低级代码重构高级语法的代码补偿包,里面包含了对高级代码的实现代码,所以它会参与构建项目,core-js 的代码也会注入到项目中。所以要 -S 安装到生产环境。
在 webpack.base.js 的 module -> rules 数组中,添加 loader 规则,module 对象可以对模块文件进行配置,rules 数组中添加规则指定 loader 加载器加载指定的文件。
```javascript
module.exports = {
module: {
rules: [ //正则匹配后缀名,指定对应的 loader
// 一定要使用 exclude 指定排除项,因为 node_modules 目录中第三方包不需要被打包
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
],
}
}
上面算是将 babel “安装”到了 webpack上,现在可以对 babel 本身进行一些功能配置
babel 配置文件.babelrc 或者babel.config.json等,具体可参考 babel 官网
babel.config.json
{
// 预设
"presets": [
[
"@babel/preset-env", // 应用预设名为 env 的 babel 解析 js
{
"targets": { // 目标浏览器,只会为这些浏览器加载 babel 来处理高阶 js
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage", // 根据运行环境动态判断是否解析高级代码
"corejs": "3.6.5" // 核心依赖库版本
}
]
]
}
.babelrc
{
// 预设
"presets": [
[
"@babel/preset-env", // 应用预设名为 env 的 babel 解析 js
{
"useBuiltIns": "usage", // 根据运行环境动态判断是否解析高级代码
"corejs": "3.6.5" // 核心依赖库版本
}
]
]
}
.babelrc 没有指明兼容的浏览器,要兼容的浏览器列表可以用 .browserslistrc文件来描述
.browserslistrc
// 多个规则之间作并集
> 25% // 兼容市面上占有率超过 0.25% 的浏览器
last 2 versions // 从最新版本向下兼容两个版本
chrome > 80 // 兼容谷歌浏览器版本大于 80 的浏览器
not ie <= 8 // 不兼容 IE 低于 8 的版本
运行npx browserslist可查看.browerslistrc文件描述的具体浏览器列表
也可以在 package.json 中描述兼容的浏览器
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
css 样式处理
4. source-map 的介绍和配置方案介绍
文档:4、Source Map.md
链接:http://note.youdao.com/noteshare?id=9ba73044baa16c6c25382eb7d7f76008&sub=B0126618269D4E6EB35F635686974907
5. 路径解析的配置方案介绍
webpack 中尽量不要使用相对路径,文件层级太多的时候,不够直观,使用绝对路径,但是从根目录开始写又过于麻烦。
所以可以把根目录到 src 目录这段路径用别名代替,常用 @ 作别名:
//webpack.base.j追加如下代码
module.exports = {
resolve:{
//配置免后缀的文件类型
extensions:['.js','.jsx','.vue','.css','.less','.scss'],
//为全路径配置缩写@
alias:{
'@':path.resolve(__dirname,'src')
}
}
}
6. webpack中文件资源处理的介绍
webpack 是无法识别其他文件,例如图片,字体,所以也需要一个加载器。通常使用 file-loader 来处理这些文件,完成自动打包和路径依赖。还有一个加载器 url-loader,封装了 file-loader,它不仅能处理图片还能对图片进行 base64 编码,形成 dataURL,直接注入到 main.bundle.js 中。
6.1 webpack 图片打包处理
HTML初次加载只会把 img 标签加入 dom 结构中,img 标签中 src 的内容是浏览器再次发送请求拿到的。多个小图就会造成大量请求,这个问题之前我们用精灵图解决,还可以用 base64 编码解决。
base64 编码把图片保存在 js 中,请求完 mian.bundel.js 后不需要再次请求服务器。不过 base64 会增大图片的体积,所以只适合小图使用。
我们在项目中有两个地方存放静态资源,分别是 public 目录下和 src 目录下。引入静态资源的方式也有两种:
- HTML 标签引入:直接在 img 上编写路径引入图片
ES6 模块化引入:通过 import 的方式引入图片,再将图片传给标签 ```html
APP
因为 url-loader 封装了 file-loader ,所以只需要配置 url-loader 就行。
```javascript
module.exports = {
mode: 'none',
module: {
rules: [
{
test: /\.jgp|png|gif$/,
loader: 'url-loader', // 只有一个loader,不用写use也行
options: {
limit: 100 * 1024, // 小于100k的图片以base64打包
name: '[name]_[hash:10].[ext]', // 打包后的名字,原名_hash值前10位.后缀名
esModule: false, // 关闭 url-loader es6 模块化解析方式,使用 CommonJs 解析
}
}
]
}
}
这里有个细节需要注意:
- html 标签引入图片的方式,webpack 无法将图片注入到 html 模板中,因为 url-loader 默认是以 es6 模块化解析图片模块。而webpack 使用的 html 模板 loader 使用的是 CommonJs 解析。
<!-- html标签引入 --> <img src="[object Module]" alt=""> <!-- 模块化引入 --> <img src="data:image/png;base64,iVBORw..." alt="">
webpack5 资源模块(替代 file-loader/url-loader/raw-loader)
7. Tree-shaking的介绍
tree-shaking 是一种技术,树摇,摇落没有依赖到的叶子节点。es6 解构赋值就是利用了这个技术从而实现了按需引入的效果。
export const userinfo = { }
export const userinfo1 = { }
export const userinfo2 = { }
-------------------------------
import { userinfo } from '@/user'


