• 带你从源码看看webpack 的构建流程(下)?


    在学习这一节要了解一些词的意思:

    moduleGraph:记录了模块和模块之间的关系,比如谁依赖谁、导出什么内容、前置执行顺序、后置执行顺序等等。
    chunkGraph:记录了哪些chunk里有哪些module,以及哪些module被哪些chunk引用了
    entrypoint:记录了入口点相关信息,包括来自哪个模块,options等

    为了简化分析流程:没有引入其它模块:
    在这里插入图片描述

    设置模块间的依赖

    进入seal阶段在这里插入图片描述
    设置模块和chunk之间的联系,哪个模块对应哪个chunk,所谓的chunk就是相当于编译的入口文件。module就是属于chunk,一个chunk对应一个或多个module。
    在这里插入图片描述
    这里还会获取当前入口去新增chunk:
    在这里插入图片描述
    然后执行buildChunkGraph:
    在这里插入图片描述
    在该函数中主要执行visitModules:

    在这里插入图片描述
    其中,最重要的就是processQueue方法:
    在这里插入图片描述
    第一步建立chunk和模块之间的关系,那么是怎么建立的呢?
    在这里插入图片描述
    首先根据模块去找到该模块映射的chunks,然后将目标chunk添加进入,再根据chunk找到该chunk下的modules,并将目标module添加进去。
    在这里插入图片描述
    第二步就是设置模块的执行顺序和设置模块的前置顺序:
    在这里插入图片描述
    设置模块的执行顺序
    在这里插入图片描述
    设置模块的前置顺序
    在这里插入图片描述
    执行完visitModules建立了模块和chunk之间的联系,接下来开始:
    在这里插入图片描述
    如果没有异步依赖就跳过这个过程。执行完buildGraph后:
    在这里插入图片描述
    createModuleHashes方法主要执行下图方法生成digest:
    在这里插入图片描述

    生成代码

    随后执行codeGeneration生成文件:
    在这里插入图片描述
    该方法首先获取该模块的chunk的hash值,并放入jobs中:
    在这里插入图片描述
    在这里插入图片描述
    主要执行下图方法:
    在这里插入图片描述
    该方法会先获取缓存,如果没有缓存则会调用module.codeGeneration方法生成代码:
    在这里插入图片描述
    然后执行NormalModule中的codeGeneration方法生成code:
    在这里插入图片描述
    这里主要执行sourceModule:
    在这里插入图片描述
    在这里插入图片描述
    在sourceDependency函数中会根据该依赖的构造函数去获取生成依赖的template,执行template的apply方法。比如import {a} from ‘b.js’,生成变量a的dependency 就是HarmonyExportSpecifierDependency。然后执行template的apply方法:
    在这里插入图片描述
    HarmonyExportSpecifierDependency的apply内容:
    在这里插入图片描述
    这里先执行getExportsInfo方法获取当前模块的exports,再执行getUsedName方法获取是否被使用:
    在这里插入图片描述
    在这里我们可以看到是否使用的标志是_usedInRuntime
    在这里插入图片描述

    设置依赖的exports

    那么这个_usedInRuntime值是什么时候去设置的呢?在所有模块都编译完毕后,会触发 compilation.hooks.finishModules 钩子,然后在FlagDependencyExportsPlugin插件里面根据依赖去设置ModuleGraph的ModuleGraphConnection的exports信息。最后在FlagDependencyUsagePlugin插件中设置_usedInRuntime的值,我们重点看FlagDependencyUsagePlugin插件中执行过程。首先根据入口文件依赖进入processEntryDependency:
    在这里插入图片描述
    在这里插入图片描述
    继续将当前模块入队列:
    在这里插入图片描述
    在这里插入图片描述
    在processModule函数中或判断当前模块是否引入其它模块:
    在这里插入图片描述
    继续往下执行,这里会保存引入的模块和变量到map当中:
    在这里插入图片描述
    继续遍历map
    在这里插入图片描述
    继续执行prcessReferencedModule函数,我们只看最关键的一段代码setUsedConditionally:
    在这里插入图片描述
    在该函数中会设置变量的_usedInRuntime值:
    在这里插入图片描述
    看到这里的小伙伴可能又有疑惑了,也没有看到什么其他的操作啊,dependency一开始就是确定的。那么依赖是怎么确定的?依赖的确定是通过传入ast去执行blockPreWalkStatements查找当前模块引入的依赖,通过walkStatements查找出自身的导出模块。

    生成标记代码

    在这里会找到当前模块的ModuleGraphModule的exports信息去判断是否被用到:
    在这里插入图片描述
    如果没有被用到那么会添加HarmonyExportInitFragment,HarmonyExportInitFragment会根据未使用的变量在打包后的内容新增unused harmony exports信息。
    在这里插入图片描述
    在这里插入图片描述
    HarmonyExportInitFragment的getContent方法:
    在这里插入图片描述
    执行完当前模块的所有依赖就会对运行时依赖执行sourceDependency方法:
    在这里插入图片描述
    最后对依赖块执行sourceDependency方法,一个blocks包括多个block,一个block包含多个依赖:
    在这里插入图片描述
    执行完sourceModule方法后开始执行addToSource方法将fragments内容放入一个数组,该数组是即将打包输出的内容,ReplaceSource会根据loc去替换原来的source:
    在这里插入图片描述
    addToSource主要循环initFragments并生成代码然后添加到source:
    在这里插入图片描述
    这里举例说明一下怎么替换的:
    替换前:
    在这里插入图片描述
    根据fragments生成的内容:

    在这里插入图片描述
    打包生成的内容:
    在这里插入图片描述
    可以看出,打包后的内容是fragment里的children的内容。这里我们再分析下HarmonyImportSpecifierDependency的apply方法:
    在这里插入图片描述
    可以看到HarmonyImportSpecifierDependency会将变量进行替换。其他的dependency的作用其实都是类似的,都起到对某个片段替换的功能。

    拿到所有result后经过一系列的缓存,然后进入codeGeneration回调:
    在这里插入图片描述

    输出代码


    emitAssets方法主要执行下图方法:
    在这里插入图片描述
    确定了输出路径,开始生成文件夹,生成文件夹后执行回调emitFiles:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    此时执行完该方法就已经生成了testxx.js文件:在这里插入图片描述
    总结:

    1. init-初始化参数
      根据用户设置的options,webpack会新增一些默认配置
    2. run-开始编译
      生成compiler,执行插件,然后执行compiler的run方法开始执行编译并生成compilation
    3. make-添加入口文件,执行loaders编译模块并解析生成模块dependencies
    4. seal-设置模块和chunk之间的关系以及模块执行顺序,标记模块导出变量
    5. emit-生成代码,并输出文件
  • 相关阅读:
    Django中使用下拉列表过滤HTML表格数据
    verilog实现串口通信发送到数码管
    【3D建模实战】维京海盗盾牌教程
    看的是SpringBoot连接mysql数据,写入数据
    彻底理解solidity中的事件
    Google Earth Engine(GEE)——
    JSplacement丨随机生成置换贴图
    图扑软件智慧云展厅,开启数字化展馆新模式
    Pytorch教程
    【计算机网络】第一章、计算机网络体系结构
  • 原文地址:https://blog.csdn.net/qq_35094120/article/details/127123401