webpack 基本流程
2021-04-27 本文已影响0人
欢欣的膜笛
Webpack 的运⾏⽅式
// 第一种:基于命令行的方式
webpack --config webpack.config.js
// 第二种:基于代码的方式
var webpack = require('webpack')
var config = require('./webpack.config')
webpack(config, (err, stats) => {})
webpack.js 中的基本流程
Webpack 函数的核⼼逻辑是:根据配置⽣成编译器实例 compiler,然后处理参数,执⾏ WebpackOptionsApply().process,根据参数加载不同内部插件。在有回调函数的情况下,根据是否是 watch 模式来决定要执⾏ compiler.watch 还是 compiler.run。
Compiler.js 中的基本流程
- readRecords:读取构建记录,⽤于分包缓存优化,在未设置 recordsPath 时直接返回。
- compile 的主要构建过程,涉及以下⼏个环节:
a. newCompilationParams:创建 NormalModule 和 ContextModule 的⼯⼚实例,⽤于创建后续模块实例。
b. newCompilation:创建编译过程 Compilation 实例,传⼊上⼀步的两个⼯⼚实例作为参数。
c. compiler.hooks.make.callAsync:触发 make 的 Hook,执⾏所有监听 make 的插件(例如 SingleEntryPlugin.js 中,会在相应的监听中触发 compilation 的 addEntry ⽅法)。其中,Hook 的作⽤,以及其他 Hook 会在下⾯的⼩节中再谈到。
d. compilation.finish:编译过程实例的 finish ⽅法,触发相应的 Hook 并报告构建模块的错误和警告。
e. compilation.seal - emitAssets:调⽤ compilation.getAssets(),将产物内容写⼊输出⽂件中。
- emitRecords:对应第⼀步的 readRecords,⽤于写⼊构建记录,在未设置 recordsPath 时直接返回。
Compilation.js 中的基本流程
- addEntry:从 entry 开始递归添加和构建模块。
- seal:冻结模块,进⾏⼀系列优化,以及触发各优化阶段的 Hooks。
执⾏ Webpack 构建时的基本流程
- 创建编译器 Compiler 实例。
- 根据 Webpack 参数加载参数中的插件,以及程序内置插件。
- 执⾏编译流程:创建编译过程 Compilation 实例,从⼊⼝递归添加与构建模块,模块构建完成后冻结模块,并进⾏优化。
- 构建与优化过程结束后提交产物,将产物内容写到输出⽂件中。
Webpack 中的插件
Webpack 引擎基于插件系统搭建⽽成,不同的插件各司其职,在 Webpack ⼯作流程的某⼀个或多个时间点上,对构建流程的某个⽅⾯进⾏处理。
⼀个 Webpack 插件是⼀个包含 apply ⽅法的 JavaScript 对象。这个 apply ⽅法的执⾏逻辑,通常是注册 Webpack ⼯作流程中某⼀⽣命周期 Hook,并添加对应 Hook 中该插件的实际处理函数。
Hook(俗称钩⼦)的使⽤⽅式
- 在构造函数中定义 Hook 类型和参数,⽣成 Hook 对象。
- 在插件中注册 Hook,添加对应 Hook 触发时的执⾏函数。
- ⽣成插件实例,运⾏ apply ⽅法。
- 在运⾏到对应⽣命周期节点时调⽤ Hook,执⾏注册过的插件的回调函数。
Compiler Hooks(构建器实例的⽣命周期)
- 初始化阶段
- 构建过程阶段
- 产物⽣成阶段
Compilation Hooks(构建过程实例的⽣命周期)
- 构建阶段
-
优化阶段
编写⼀个统计构建过程⽣命周期耗时的插件
class SamplePlugin {
apply(compiler) {
var start = Date.now()
var statsHooks = ['environment', 'entryOption', 'afterPlugins', 'compile']
var statsAsyncHooks = ['beforeRun', 'beforeCompile', 'make', 'afterCompile', 'emit', 'done']
statsHooks.forEach((hookName) => {
compiler.hooks[hookName].tap('Sample Plugin', () => {
console.log(`Compiler Hook ${hookName}, Time: ${Date.now() - start}ms`)
})
})
// ···
}
})
module.exports = SamplePlugin;