Skip to content

构建流程

工作流程

webpack 的工作流程是一个串行的过程,从启动到结束会依次执行以下流程:

  1. 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
  2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
  3. 确定入口:根据配置中的 entry 确定入口文件;
  4. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行编译,再找出该模块依赖的模块,得到了每个模块被编译后的 最终内容 以及他们之间的 依赖关系图
  5. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
  6. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

常见的问题

Module、Chunk、Bundle 的区别

module: 模块,一个模块就是一个文件

chunk: 代码块,一个 chunk 可以由多个模块组合而成

bundle: webpack 打包出来的文件

Loader 和 Plugin

loader 是一个加载器,让 webpack 拥有加载和解析非 JavaScript 文件的能力

Plugin 是一个插件,是对 webpack 功能的扩展,让 webpack 具有更高的灵活性

Compiler 和 Compilation 的区别

Compiler 对象在 webpack 启动时候被实例化,可以访问当前运行的 webpack 配置,包括 entry、output、loader 等配置,它是全局唯一的。

Plugin 的 apply 方法会传入一个 Compiler 对象,通过这个 Compiler 对象可以注册各种钩子函数,执行插件任务,也可以通过该对象获取配置信息。

js
Compiler.plugin('emit', function(compilation, callback) {
    // emit 是异步 hook, 在生成之前输出到目录之前调用
 });
Compiler.plugin('emit', function(compilation, callback) {
    // emit 是异步 hook, 在生成之前输出到目录之前调用
 });

Compilation 对象是 Compiler 用来常见新的编译流程,每当检测到新的文件变化,就会创建新的 compilation。他可以访问所有的模块和依赖关系

在编译流程中,涉及了 编译优化分块 等阶段。

js
compilation.hooks.someHook.tap('SomePlugin', () => {
    // 这里是异步的
});
compilation.hooks.someHook.tap('SomePlugin', () => {
    // 这里是异步的
});

热更新原理

webpack4 和 webpack5 的区别

1 强化 Tree Shaking

  • 可以处理 CommonJS 的代码

2 压缩代码

  • 内置了 js 的压缩功能 (terser-webpack-plugin)

3 缓存配置

  • webpack4 需要安装 HardSourceWebpackPlugin 插件
  • 内置了 cache 缓存机制
js
// webpack.config.js
module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename], // 当配置修改时,缓存失效
    },
  },
};
// webpack.config.js
module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename], // 当配置修改时,缓存失效
    },
  },
};

4 sideEffects

  • webpack4 需要配置 sideEffects: false
  • webpack5 可以根据源代码静态分析,自动将模块标记成无副作用。

5 支持 import 加载异步模块

6 支持模块联邦

参考文章