webpack 4 源码主流程分析(十一):文件的生成
资源写入文件
回到 seal
。执行:
1 | this.summarizeDependencies(); |
得到 this.fileDependencies, this.contextDependencies, this.missingDependencies
后,触发了一系列处理资源,优化资源的钩子之后,回到 Compiler.js
的 compile
里的 compilation.seal
回调。
执行:
1 | this.hooks.afterCompile.callAsync(compilation, (err) => { |
该钩子会触发插件 CachePlugin
相关的事件,给 compiler
的属性 _lastCompilationFileDependencies,_lastCompilationContextDependencies
分别赋值 fileDependencies,contextDependencies
。
创建目标文件夹
然后执行回调即 onCompiled
,方法里执行:
1 | this.emitAssets(compilation, (err) => { |
进入 this.emitAssets
,emitAssets
负责的是构建资源输出的过程。在方法里触发了 Compiler.hooks
:emit
,在回调里执行:
1 | //... |
outputPath
为配置里的 output.path
,然后调用 mkdirp
创建文件夹。
创建目标文件并写入
创建目标文件夹后,执行回调 emitFiles
,在回调里通过 asyncLib.forEachLimit
并行执行对每个 file
资源文件进行路径拼接后,将每个 source
源码转换为 buffer
后(性能提升),写入真实路径的 file
:
1 | asyncLib.forEachLimit( |
其中:
1 | let content = source.source(); |
source
为 CachedSource
实例,source.source
做了缓存判断,执行 this._source.source
, this._source
为 ConcatSource
实例,该方法会遍历 children
,如果子项不是字符串,则执行其 source
方法。
对于 ReplaceSource
实例来说,会执行其 _replaceString
方法,该方法里会循环处理替换在之前 资源的构建 -> 生成 chunk 资源 -> chunkTemplate -> 生成主体 chunk 代码 -> 生成每个 module 代码
push
进去的 replacements
,得到替换后的字符串,合并返回 resultStr
。
设置 stats 并打印构建信息
所有文件都创建写入完成后,执行回调:
1 | this.hooks.afterEmit.callAsync(compilation, (err) => { |
在回调里触发 Compiler.afterEmit
:hooks
,在回调里执行 callback
即 onCompiled
里的 this.emitAssets
的回调,即执行:
1 | //... |
执行 this.emitRecords
,然后在其回调里设置相关 stats
,然后在 Compiler.done
:hooks
的回调里执行 finalCallback
,即执行文件 webpack-cli/bin/cli.js
里的 compiler.run
的回调,即 compilerCallback
。
方法里清除缓存之后,执行:
1 | const statsString = stats.toString(outputOptions); |
在 cli
里打印出构建相关的信息。至此,构建全部结束,下一章分析打包后的文件!
本章小结
- 创建目标文件夹及文件并将资源写入;
- 写入的时候,会循环处理
source
中的ReplaceSource
实例中的replacements
,将其替换为真实字符串; - 设置
stats
并打印构建信息。