amandakelake/blog

【webpack进阶系列】seal封装生成文件核心流程

amandakelake opened this issue · 2 comments

一、前言

【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这个词就知道了
28226861-520E-45A7-A3A4-F5E6A50EE3C8

这里有个地方注意一下,优化类的插件全部是同步钩子(做优化当然是一步步像个水管一样流动,异步的话互相穿插很容易混淆插件之间的入口代码)

优化完成后根据entry创建第一类chunk,有多少个entry module就创建多少个chunk,然后根据chunk递归处理是否有异步module,创建二类chunk,然后调用createChunkAssets根据不同的模板来生成源码对象,最后再缓存和生成sourceMap,最后存放到compilation.assets
EBCDAC7F-6001-4140-A1EF-DC53906B91AA

关于template,compilation在实例化的时候,就已经实例化了3个对象
* mainTemplate
* chunkTemplate
* moduleTemplates
三个对象的作用分别如图
ECD63121-B214-4621-8184-CD376E1F41EC
4ZUS64uSa5knwh3-zLwQW-yg_KVM_wRS7m7qOfo5US6WaPbQIZLQe624-jfLKDYJoPrsqdPnde0iswdVjaZwI9De8hSelZkbaogdc5WcJnbZXU21P_wTmDfzxYsMlMJ9BlIu7mT0tS8

seal后存放在compilation.assets里最后的产物,每个entry模块对应一个key对象,里面的动态chunk存放在children数组中
4E7C1187-301F-4E26-A61C-14D30D3B000B

四、输出文件

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,个人是这样理解