概念
- Webpack 是一个静态模块打包工具,从入口构建依赖图,打包有关的模块,最后用于展示你的内容
- 静态模块:编写代码过程中的,html,css, js,图片等固定内容的文件
- 打包过程,注意:只有和入口有直接/间接引入关系的模块,才会被打包
- Webpack 的作用:把静态模块内容,压缩,整和,转译等(前端工程化)
- 把 less/sass 转成 css 代码
- 把 ES6+ 降级成 ES5 等
- 支持多种模块文件类型,多种模块标准语

使用
要求:封装 utils 包,校验手机号和验证码长度,在 src/index.js 中使用,使用 Webpack 打包
步骤:
- 新建项目文件夹 Webpack_study,初始化包环境,得到 package.json 文件
1 | npm init -y |
- 新建 src 源代码文件夹(书写代码)包括 utils/check.js 封装用户名和密码长度函数,引入到 src/index.js 进行使用
- src/utils/check.js
1 | // 封装校验手机号长度和校验验证码长度的函数 |
- src/index.js
1 | /** |
- 下载 webpack webpack-cli 到项目(版本独立)
1 | npm i webpack webpack-cli --save-dev |
📌注意:虽然 webpack 是全局软件包,封装的是命令工具,但是为了保证项目之间版本分别独立,所以这次比较特殊,下载到某个项目环境下,但是需要把 webpack 命令配置到 package.json 的 scripts 自定义命令,作为局部命令使用

- 项目中运行工具命令,采用自定义命令的方式(局部命令)
1 | npm run build |
- 自动产生 dist 分发文件夹(压缩和优化后,用于最终运行的代码)

搭建开发环境
使用
- 每次改动代码,都要重新打包,很麻烦,所以这里给项目集成 webpack-dev-server 开发服务器
- 作用:启动 Web 服务,打包输出源码在内存,并会自动检测代码变化热更新到网页
- 步骤;
- 下载 webpack-dev-server 软件包到当前项目
- 配置自定义命令,并设置打包的模式为开发模式
1
2
3
4module.exports = {
// ...
mode: 'development'
}1
2
3"scripts": {
"dev": "webpack serve --mode=development"
}, - 使用 npm run dev 来启动开发服务器,访问提示的域名+端口号,在浏览器访问打包后的项目网页,修改代码后试试热更新效果
注意:
- webpack-dev-server借助 http模块创建8080 默认 Web服务
- 默认以 public 文件夹作为服务器根目录
- webpack-dev-server根据配置,打包相关代码在内存当中,以 output.path 的值作为服务器根目录(所以可以直接自己拼接访问dist目录下内容)|
热更新原理
Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。
webpack的构建流程
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译确定入口:根据配置中的 entry 找出所有的入口文件编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。
简单说
- 初始化:启动构建,读取与合并配置参数,加载 Plugin,实例化 Compiler
- 编译:从 Entry 出发,针对每个 Module 串行调用对应的 Loader 去翻译文件的内容,再找到该 Module 依赖的 Module,递归地进行编译处理
- 输出:将编译后的 Module 组合成 Chunk,将 Chunk 转换成文件,输出到文件系统中
修改出入口
- 项目根目录,新建 Webpack.config.js 配置文件
- 导出配置对象,配置入口,出口文件路径(别忘了修改磁盘文件夹和文件的名字)
1 | const path = require('path') |
- 重新打包
设置解析别名路径
- 解析别名:配置模块如何解析,创建 import 或 require 的别名,来确保模块引入变得更简单
- 例如:
- 原来路径如下:b. 配置解析别名:在 webpack.config.js 中设置
1
import { checkPhone, checkCode } from '../src/utils/check.js'
c. 这样我们以后,引入目标模块写的路径就更简单了1
2
3
4
5
6
7
8const config = {
// ...
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}1
import { checkPhone, checkCode } from '@/utils/check.js'
- 原来路径如下:
引入插件(plugin)
- 插件 html-webpack-plugin 作用:在 Webpack 打包时生成 html 文件,并引入其他打包后的资源
- 步骤:
- 下载 html-webpack-plugin 本地软件包到项目中
1 | npm i html-webpack-plugin --save-dev |
- 配置 webpack.config.js 让 Webpack 拥有插件功能
1 | const HtmlWebpackPlugin = require('html-webpack-plugin') |
- 指定以 public/login.html 为模板复制到 dist/login/index.html,并自动引入其他打包后资源
- 运行打包命令,观察打包后 dist 文件夹下内容并运行查看效果
加载器(loader)
Webpack 默认只识别 JS 和 JSON 文件内容,所以想要让 Webpack 识别更多不同内容,需要使用加载器。
- 加载器 css-loader:解析 css 代码
- 加载器 style-loader:把解析后的 css 代码插入到 DOM(style 标签之间)
- 加载器 less-loader:把 less 代码编译为 css 代码,还需要依赖 less 软件包
步骤:
- 准备 css 文件引入到 src/login/index.js 中(压缩转译处理等)
1 | /** |
注意:这里只是引入代码内容让 Webpack 处理,不需定义变量接收在 JS 代码中继续使用,所以没有定义变量接收
- 下载 css-loader 和 style-loader 本地软件包
1 | npm i css-loader style-loader --save-dev |
- 配置 webpack.config.js 让 Webpack 拥有该加载器功能
1 | module.exports = { |
- 打包后运行 dist/login/index.html 观察效果,看看准备好的样式是否作用在网页上
loader和plugin的区别
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
打包图片
资源模块:Webpack 内置了资源模块的打包,无需下载额外 loader
步骤:
配置 webpack.config.js 让 Webpack 拥有打包图片功能
占位符 【hash】对模块内容做算法计算,得到映射的数字字母组合的字符串
占位符 【ext】使用当前模块原本的占位符,例如:.png / .jpg 等字符串
占位符 【query】保留引入文件时代码中查询参数(只有 URL 下生效)
注意:判断临界值默认为 8KB
大于 8KB 文件:发送一个单独的文件并导出 URL 地址
小于 8KB 文件:导出一个 data URI(base64字符串)
在 src/login/index.js 中给 img 标签添加 logo 图片
1 | /** |
- 配置 webpack.config.js 让 Webpack 拥有打包图片功能
1 | module.exports = { |