原稿:语雀 · webpack 知识点 · 原目录:Webpack › webpack 知识点
为什么要使用 webpack,不直接 require?
直接 require,而不打包,每个模块都会单独通过 http 传输下载并加载,而打包后就只有一个模块需要下载。编译后打包减少了页面的 http 请求,减少了页面加载时间,从而增加了页面的显示速度
webpack 核心概念
- 入口(entry):入口起点(entry point)指示 webpack 应该使用哪个模块作为构建内部依赖图(dependency graph) 的开始。进入入口起点后,webpack 会递归地找出有哪些模块和库是入口起点依赖的
- 模块(module):在 webpack 中,一个模块对应一个文件
- 代码块(Chunk):代码块,一个 chunk 由多个模块组合而成,用于代码合并与分割
- 加载器(loader):webpack 只能理解 JavaScript 和 JSON 文件,而各种 loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中
- 插件(plugin):loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量
- 输出(output):输出属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中
- 输出束(bundle):由许多不同的模块生成,是已经经过加载和编译过程的源文件的最终版本
如何区分 module、chunk、bundle?
参考链接:webpack 中,module,chunk 和 bundle 的区别是什么?

一般来说一个 chunk 对应一个 bundle,比如上图中的 utils.js -> chunks 1 -> utils.bundle.js;但也有例外,比如说上图中,使用 MiniCssExtractPlugin 从 chunks 0 中抽离出了 index.bundle.css 文件
总结:module,chunk 和 bundle 其实就是同一份逻辑代码在不同转换场景下的取了三个名字:未经打包的源文件是 module,chunk 强调 webpack 模块捆绑过程,最后生成浏览器可以直接运行的 bundle |
webpack 构建流程
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程: 2. 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数; 4. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译; 6. 确定入口:根据配置中的 entry 找出所有的入口文件; 8. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理; 10. 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系; 12. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会; 14. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果
loader 与 plugin
Loader 和 Plugin 区分
loader | plugin | |
作用 | Webpack 将一切文件视为模块,但是原生只能解析 js 和 json 文件,如果想将其他文件也作为模块处理,就会用到 loader,所以 Loader的作用是让 webpack 拥有了加载和解析非 JS 文件的能力 | Plugin 可以扩展 webpack 的功能,让 webpack 具有更多的灵活性,解决 loader 无法实现的事情。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。 |
用法 | 通常在 module.rules 中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个 Object,里面描述了对于什么类型的文件(test),使用什么 loader 加载 (use) 和以及参数(options) | 在配置文件中引入,在 module.plugins 中通过 new 实例化 |
![]() | ![]() |
Loader 原理
loader 到底做了什么?
由于 webpack 是基于Node 的所以 webpack 只能识别 js 文件,所以针对其他的文件就需要转译。loader 是文件加载器,能够加载不同类型资源文件,并对这些文件进行特定的处理,然后打包的指定文件中,简单来说就是将webpack 传入的字符串做出特定的处理修改
loader 特点
- loader 的执行顺序和配置文件 use 引用顺序相反,即:最后一个 loader 最先执行,第一个 loader 最后执行
- 第一个执行的 loader 会接收源文件做为参数,下一次执行的 loader 会接收前一个 loader 执行的返回值做为参数
loader 编写原则
- 单一原则:每个 Loader 只做一件事;
- 链式调用:Webpack 会链式依次调用每个 Loader;
- 统一原则:遵循 Webpack 制定的设计规则和结构,输入与输出均为字符串,各个 Loader 完全独立,即插即用;
可以自己编写一个 Demo 帮助理解
Plugin 原理
相对于Loader而言,Plugin的编写就灵活了许多。 webpack在运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果
常见 loader |
|
常见 plugin |
|
dev-server 热更新原理
webpack 优化
模块加载
参考链接:简单易懂的 webpack 打包后 JS 的运行过程
webpack打包出来的是js插在模板可以允许和渲染是怎么实现的
当之后以下两个模块时
// test.js
const str = 'test is loaded';
module.exports = str;
// index.js
const test = require('./src/js/test');
console.log(test);
编译打包后的模块结构

