blog
blog copied to clipboard
【webpack进阶系列】seal封装生成文件核心流程
一、前言
【webpack进阶系列】构建module核心流程 在前面
make
钩子,已经把所有的modules编译完成并存放在compilation.modules
中,数据结构大概如下
compilation = {
// ...
modules: [{
// ...
dependencies: [{
// ...
module: {
// ...
dependencies: [{
// ...
module: {
// ... 不断递归
}
}]
}
}, {}]
}, {}]
};
根据以上compilation.modules
的数据结构,webpack已经有能力找到所有的依赖,那么接下来就是如何把这些modules进行封装
二、总览
seal
的任务是把上面的modules生成chunk,生成最终源码存放在compilation.assets
属性上(期间有各种性能优化)
在webpack中chunk的概念有两个 * 配置在entry的模块,也就是入口文件 * 动态引入的模块(require/import进来的)
每个chunk其实就是找到以上两种概念中的一个模块,entry module和动态module生成的chunk的区别在于后面调用的模板不一样
这里模板的概念,是指根据chunk调用模板的render
方法渲染成源码,entry module选择mainTemplate
,动态module选择chunkTemplate
三、compilation.seal
seal的前面很大一部分代码都是调用性能优化相关的内置插件,对模块做最后的优化,搜一下optimize
这个词就知道了
这里有个地方注意一下,优化类的插件全部是同步钩子(做优化当然是一步步像个水管一样流动,异步的话互相穿插很容易混淆插件之间的入口代码)
优化完成后根据entry创建第一类chunk,有多少个entry module就创建多少个chunk,然后根据chunk递归处理是否有异步module,创建二类chunk,然后调用createChunkAssets
根据不同的模板来生成源码对象,最后再缓存和生成sourceMap,最后存放到compilation.assets
中
关于template,compilation
在实例化的时候,就已经实例化了3个对象
* mainTemplate
* chunkTemplate
* moduleTemplates
三个对象的作用分别如图
seal后存放在compilation.assets
里最后的产物,每个entry模块对应一个key对象,里面的动态chunk存放在children
数组中
四、输出文件
seal完成后,一路回到compiler.run -> this.compile(onCompiled) -> this.emitAssets
,也就是调用compiler.emitAssets
,按照output
的配置,通过outputFileSystem.writeFile
把结果输出到文件中,至此,webpack整个打包流程结束
我调试之后发现,Webpack5 compilation.modules的数据结构是这样的:
{
...
modules: [
{
dependencies: [{
moduleA,
moduleB
}]
},
moduleA,
moduleB
],
...
}
是版本升级的变化吗?
我调试之后发现,Webpack5 compilation.modules的数据结构是这样的:
{ ... modules: [ { dependencies: [{ moduleA, moduleB }] }, moduleA, moduleB ], ... }
是版本升级的变化吗?
不是的,一直都是这样,本来就是依赖图moduleGraph。图是松散结构,如果有多个入口的话,依赖一个module的话,多个树中都有这个module实例的引用,就可以做optimize,个人是这样理解