webpack 编译流程

本文详细介绍了Webpack的编译流程,包括初始化参数、构建Compiler对象、加载插件、执行run方法、查找入口文件、模块编译及依赖分析、组装Chunk、生成输出文件等步骤,并深入探讨了Compiler和Compilation的概念及其区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

webpack 编译流程

整体流程

  1. 初始化参数:从配置文件和Shell语句中读取并合并参数,得出最终的配置对象
  2. 用上一步得到的参数初始化Compiler对象
  3. 加载所有配置的插件(依次调用插件中的apply方法)
  4. 执行对象的run(Compiler.run)方法开始执行编译
  5. 根据配置中的entry找出入口文件
  6. 从入口文件出发,调用所有配置的Loader对模块进行编译
  7. 再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
  8. 根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk
  9. 再把每个Chunk转换成一个单独的文件加入到输出列表
  10. 在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统(dist/build目录)

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果

在这里插入图片描述


一些细节

根据配置中的entry找出入口文件后,从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理,再根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk。

在上面的这一步骤中,具体流程如下:

  1. 获取主模块内容

  2. 分析模块

  • 安装@babel/parser包(转AST)
  1. 对模块内容进行处理
  • 安装@babel/traverse包(遍历AST收集依赖)
  • 安装@babel/core和@babel/preset-env包 (es6转ES5)
  1. 递归所有模块

  2. 生成最终代码


核心概念

  • Entry:入口,webpack构建的起始

  • Module:模块,webpack里面一切皆模块,也是代表着文件,从Entry配置的入口文件开始,递归找出依赖的模块

  • Chunk:代码块,找出递归依赖模块经转换后组合成代码块

  • Loader:模块转换器,也就是将模块的内容按照需求装换成新内容

  • Plugin:扩展插件,webpack构建过程中,会在特定的时机广播对应的事件,而插件可以监听这些事件的发生


Compiler 和 Compilation 的区别

webpack 打包离不开 CompilerCompilation,它们两个分工明确,理解它们是我们理清 webpack 构建流程重要的一步。


Compiler

Compiler 负责监听文件和启动编译 它可以读取到 webpack 的 config 信息,整个 Webpack 从启动到关闭的生命周期,一般只有一个 Compiler 实例,整个生命周期里暴露了很多方法,常见的 run,make,compile,finish,seal,emit 等,我们写的插件就是作用在这些暴露方法的 hook 上

compiler 对象中保存着完整的 Webpack 环境配置,每次启动 webpack 构建时它都是一个独一无二,仅仅会创建一次的对象。

这个对象会在首次启动 Webpack 时创建,我们可以通过 compiler 对象上访问到 Webapck 的主环境配置,比如 loader 、 plugin 等等配置信息。

它有以下主要属性:

  • compiler.options 可以访问本次启动 webpack 时候所有的配置文件,包括但不限于 loaders 、 entry 、 output 、 plugin 等等完整配置信息。
  • compiler.inputFileSystemcompiler.outputFileSystem 可以进行文件操作,相当于 Nodejs 中 fs。
  • compiler.hooks 可以注册 tapable 的不同种类 Hook,从而可以在 compiler 生命周期中植入不同的逻辑。

Compilation

Compilation 负责构建编译。 每一次编译(文件只要发生变化,)就会生成一个 Compilation 实例,Compilation 可以读取到当前的模块资源,编译生成资源,变化的文件,以及依赖跟踪等状态信息。同时也提供很多事件回调给插件进行拓展。

一个 compilation 对象会对构建依赖图中所有模块,进行编译。 在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、 分块(chunk)、哈希(hash)和重新创建(restore)。

它有以下主要属性:

  • compilation.modules 可以访问所有模块,打包的每一个文件都是一个模块。
  • compilation.chunks chunk 即是多个 modules 组成而来的一个代码块。入口文件引入的资源组成一个 chunk,通过代码分割的模块又是另外的 chunk。
  • compilation.assets 可以访问本次打包生成所有文件的结果。
  • compilation.hooks 可以注册 tapable 的不同种类 Hook,用于在 compilation 编译模块阶段进行逻辑添加以及修改。

Webpack 内部的钩子

钩子的本质就是:事件。为了方便我们直接介入和控制编译过程,webpack 把编译过程中触发的各类关键事件封装成事件接口暴露了出来。这些接口被很形象地称做:hooks(钩子)。开发插件,离不开这些钩子


一些问题

  1. webpack 与 babel 分别实现了什么?
  • Webpack 读出 AST 之后仅遍历 AST 集合;babel 则对源码做等价转换
  1. Webpack 编译过程中,如何识别资源对其他资源的依赖?
  • Webpack 遍历 AST 集合过程中,识别 require/ import 之类的导入语句,确定模块对其他资源的依赖关系

生命周期简图

在这里插入图片描述

### 如何配置 Webpack 编译和加载 SVG 文件 #### 使用 `svg-inline-loader` 加载内联SVG文件 对于希望在React组件中直接使用SVG文件的情况,可以采用`svg-inline-loader`来实现。这有助于简化开发流程并允许更灵活的操作SVG内容[^2]。 ```javascript module.exports = { module: { rules: [ { test: /\.svg$/, use: ['svg-inline-loader'] } ] } }; ``` 上述配置使得所有匹配`.svg`扩展名的模块都将被`svg-inline-loader`处理,从而可以直接作为JSX中的标签引入到React组件里。 #### Vue项目中批量导入SVG图标 针对Vue框架下的应用,在项目的入口文件(如`main.js`或`main.ts`),可以通过编程方式批量导入位于特定目录下的所有SVG文件。这种方法不仅提高了效率也增强了灵活性[^3]。 ```javascript import { createApp } from 'vue'; import App from './App.vue'; // 批量导入SVG图标 const req = require.context('./assets/icons', false, /\.svg$/); req.keys().forEach(req); createApp(App).mount('#app'); ``` 这段代码利用了Webpack提供的`require.context()`函数创建了一个上下文环境,用于按需加载指定路径下所有的SVG资源,并立即执行这些请求以完成实际的导入操作。 #### 利用 `svg-react-loader` 实现更多功能 如果目标是在React环境中进一步增强对SVG的支持,则可以选择`svg-react-loader`。它除了支持基本的内联SVG外,还提供了诸如SVG组合、优化以及动态生成等功能,能够更好地满足复杂应用场景的需求[^1]。 ```javascript { test: /\.(svg)(\?.*)?$/, loader: "svg-react-loader" } ``` 此规则定义告诉Webpack当遇到SVG文件时应该调用哪个loader来进行转换工作。通过这种方式,不仅可以享受内联带来的便利,还能借助额外特性提高性能与用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛小y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值