Webpack 是什么?它主要解决了什么问题?
- Webpack 本质上是一个静态模块打包器。会从配置的 Entry 出发,分析模块之间的 import、require 等依赖关系,递归构建 Module Graph。
- 在构建过程中,可以通过 Loader 对不同类型的资源进行转换,例如通过 babel-loader 处理 JavaScript,通过 less-loader、css-loader 等处理样式资源。
- 在构建出模块依赖图之后,Webpack 会根据入口、动态 import、SplitChunks 等规则组织 Chunk,并最终生成浏览器可以加载的 Assets。 同时 Webpack 还提供 Plugin 机制,可以介入整个构建生命周期,实现资源优化、环境变量注入等能力。 工程层面还提供了 Tree Shaking、Code Splitting、缓存、HMR 等能力,用于优化生产环境性能以及开发体验。
Webpack 从执行 webpack 命令开始,到最终生成 dist 文件,中间完整的构建流程是什么?(重点)
- 首先会基于cli命令解析参数,并加载配置文件得到最终配置
- 然后根据配置创建Compiler,并调用各个Plugin的apply方法,生命周期hook上注册Plugin
- 初始化完成后通过compiler.run开始构建,创建一次Compilation
- 从entry开始构建Module,这过程中会通过resolve找到对应的文件,通过Loader进行转换,然后对代码进行解析,识别依赖关系
- 根据这些依赖继续递归构建其他module,形成完整的图。
- 有了图之后,会根据 Entry、动态 import、SplitChunks 等规则组织 Module 形成 Chunk,然后进行代码生成,最终形成 Assets。
- 在 emit 阶段,根据 output 配置将 Assets 写入文件系统,最终生成 dist 文件。
Compiler 是什么?
compiler代表一个Webpack编译器实例,管理整个Webpack的构建环境和生命周期。持有配置、文件系统、缓存以及各种生命周期 Hooks。 Compilation代表一次具体的构建过程,保存这次构建产生的 Module、Chunk、Asset、Dependency、Error、Warning 等信息。 Webpack 将两者拆分,本质上是为了分离长期状态和一次性状态,避免多次构建之间的数据污染,同时也让 Watch 和 HMR 能够在复用 Compiler 的基础上,仅重新创建新的 Compilation,提高构建效率。
Module / Chunk / Asset 是什么?他们之间有什么关系?
都属于某一次Compilation的构建数据,都由Compilation管理。 Module:是 Webpack 构建和依赖分析的基本单位,各个 Module 之间的依赖关系形成 Module Graph。 Chunk: Webpack 对 Module 进一步组织形成的代码块,它更关注代码如何组织以及加载边界。一个 Chunk 可以包含多个 Module,同一个 Module 也可能与多个 Chunk 产生关联。 Asset: Webpack 最终准备输出到文件系统的资源,比如 JS、CSS、图片等。 Module解决的是依赖关系,Chunk解决的是代码如何组织和加载,Asset 是最终输出阶段的资源 整体可以理解为 Webpack 先构建 Module Graph,再根据 Entry、动态 import、SplitChunks 等规则组织 Chunk,最后经过代码生成和资源处理形成 Assets 并输出。
Webpack 从 Entry 开始以后,是如何一步一步构建出 Module Graph 的?
Webpack 会从 Entry 开始创建并构建 Module,根据配置匹配对应的 Loader 对模块内容进行转换。 转换之后,Parser 会对代码进行语法分析,通过 AST 识别 import、require、动态 import() 等依赖,并形成对应的 Dependency。 Webpack 再根据 Dependency,通过 Module Resolution(.js .ts) 确定依赖对应的实际资源,然后继续创建和构建新的 Module。 新 Module 又会经历 Loader 转换、Parser 分析以及依赖解析。Webpack 递归执行这个过程,最终构建出完整的 Module Graph。
什么是webpackRuntime?webpack_require 主要做了什么?为什么 Webpack 还需要 Module Cache?
Webpack Runtime 是 Webpack 为了让打包后的模块能够在浏览器中正确加载、执行和管理而生成的一套运行时机制。 webpack_require 主要根据 Module ID 找到对应模块,执行模块代码并返回 module.exports。 同时 Runtime 会维护 Module Cache。第一次执行模块时会将 Module 缓存起来,之后其他模块再次 require 同一个 Module 时,可以直接返回缓存中的 exports,避免模块被重复执行。
动态import 如何加载chunk?
Webpack 构建阶段发现动态 import() 后,会形成异步加载边界,并可能将对应 Module 组织到独立的异步 Chunk。 浏览器运行到动态 import 时,Webpack Runtime 会先判断对应 Chunk 是否已经加载。如果没有,就根据 Chunk 信息确定资源地址,在浏览器环境下通过动态创建 script 标签等方式加载对应 Chunk。 Chunk 下载并执行之后,会把其中的 Module 注册到 Webpack 的模块系统。Chunk 加载完成后,再执行目标 Module 并获得它的 exports,最终完成动态 import 对应 Promise 的解析。