初始化阶段:
- 初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。这个过程中还会执行配置文件中的插件实例化语句 new Plugin()。
- 初始化默认参数配置: new WebpackOptionsDefaulter().process(options)
- 实例化Compiler对象:用上一步得到的参数初始化Compiler实例,Compiler负责文件监听和启动编译。Compiler实例中包含了完整的Webpack配置,全局只有一个Compiler实例。
- 加载插件: 依次调用插件的apply方法,让插件可以监听后续的所有事件节点。同时给插件传入compiler实例的引用,以方便插件通过compiler调用Webpack提供的API。
- 处理入口: 读取配置的Entrys,为每个Entry实例化一个对应的EntryPlugin,为后面该Entry的递归解析工作做准备。
编译阶段:
- run阶段:启动一次新的编译。this.hooks.run.callAsync。
- compile: 该事件是为了告诉插件一次新的编译将要启动,同时会给插件带上compiler对象。
- compilation: 当Webpack以开发模式运行时,每当检测到文件变化,一次新的Compilation将被创建
- 一个Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。
- Compilation对象也提供了很多事件回调供插件做扩展。
- make:一个新的 Compilation 创建完毕主开始编译 完毕主开始编译this.hooks.make.callAsync。
- addEntry: 即将从 Entry 开始读取文件。
- _addModuleChain: 根据依赖查找对应的工厂函数,并调用工厂函数的create来生成一个空的MultModule对象,并且把MultModule对象存入compilation的modules中后执行MultModule.build。
- buildModules: 使用对应的Loader去转换一个模块。开始编译模块,this.buildModule(module) buildModule(module, optional, origin,dependencies, thisCallback)。
- build: 开始真正编译模块。
- doBuild: 开始真正编译入口模块。
- normal-module-loader: 在用Loader对一个模块转换完后,使用acorn解析转换后的内容,输出对应的抽象语法树(AST),以方便Webpack后面对代码的分析。
- program: 从配置的入口模块开始,分析其AST,当遇到require等导入其它模块语句时,便将其加入到依赖的模块列表,同时对新找出的依赖模块递归分析,最终搞清所有模块的依赖关系。
文件输出阶段:
- seal: 封装 compilation.seal seal(callback)。
- addChunk: 生成资源 addChunk(name)。
- createChunkAssets: 创建资源 this.createChunkAssets()。
- getRenderManifest: 获得要渲染的描述文件 getRenderManifest(options)。
- render: 渲染源码 source = fileManifest.render()。
- afterCompile: 编译结束 this.hooks.afterCompile。
- shouldEmit: 所有需要输出的文件已经生成好,询问插件哪些文件需要输出,哪些不需要。this.hooks.shouldEmit。
- emit: 确定好要输出哪些文件后,执行文件输出,可以在这里获取和修改输出内容。
- done: 全部完成 this.hooks.done.callAsync。