You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// part 1: 引入的主要是 ES Module 当中使用的不同语法的依赖类型constHarmonyCompatibilityDependency=require("./HarmonyCompatibilityDependency");constHarmonyInitDependency=require("./HarmonyInitDependency");constHarmonyImportSpecifierDependency=require("./HarmonyImportSpecifierDependency");constHarmonyImportSideEffectDependency=require("./HarmonyImportSideEffectDependency");constHarmonyExportHeaderDependency=require("./HarmonyExportHeaderDependency");constHarmonyExportExpressionDependency=require("./HarmonyExportExpressionDependency");constHarmonyExportSpecifierDependency=require("./HarmonyExportSpecifierDependency");constHarmonyExportImportedSpecifierDependency=require("./HarmonyExportImportedSpecifierDependency");constHarmonyAcceptDependency=require("./HarmonyAcceptDependency");constHarmonyAcceptImportDependency=require("./HarmonyAcceptImportDependency");constNullFactory=require("../NullFactory");// part 2: 引入的主要是 ES Module 使用的不同的语法,在编译过程中需要挂载的 hooks,方便做依赖收集constHarmonyDetectionParserPlugin=require("./HarmonyDetectionParserPlugin");constHarmonyImportDependencyParserPlugin=require("./HarmonyImportDependencyParserPlugin");constHarmonyExportDependencyParserPlugin=require("./HarmonyExportDependencyParserPlugin");constHarmonyTopLevelThisParserPlugin=require("./HarmonyTopLevelThisParserPlugin");classHarmonyModulesPlugin{constructor(options){this.options=options;}apply(compiler){compiler.hooks.compilation.tap("HarmonyModulesPlugin",(compilation,{ normalModuleFactory })=>{compilation.dependencyFactories.set(HarmonyCompatibilityDependency,newNullFactory());// 设置对应的依赖渲染所需要的模板compilation.dependencyTemplates.set(HarmonyCompatibilityDependency,newHarmonyCompatibilityDependency.Template());compilation.dependencyFactories.set(HarmonyInitDependency,newNullFactory());compilation.dependencyTemplates.set(HarmonyInitDependency,newHarmonyInitDependency.Template());compilation.dependencyFactories.set(HarmonyImportSideEffectDependency,normalModuleFactory);compilation.dependencyTemplates.set(HarmonyImportSideEffectDependency,newHarmonyImportSideEffectDependency.Template());compilation.dependencyFactories.set(HarmonyImportSpecifierDependency,normalModuleFactory);compilation.dependencyTemplates.set(HarmonyImportSpecifierDependency,newHarmonyImportSpecifierDependency.Template());compilation.dependencyFactories.set(HarmonyExportHeaderDependency,newNullFactory());compilation.dependencyTemplates.set(HarmonyExportHeaderDependency,newHarmonyExportHeaderDependency.Template());compilation.dependencyFactories.set(HarmonyExportExpressionDependency,newNullFactory());compilation.dependencyTemplates.set(HarmonyExportExpressionDependency,newHarmonyExportExpressionDependency.Template());compilation.dependencyFactories.set(HarmonyExportSpecifierDependency,newNullFactory());compilation.dependencyTemplates.set(HarmonyExportSpecifierDependency,newHarmonyExportSpecifierDependency.Template());compilation.dependencyFactories.set(HarmonyExportImportedSpecifierDependency,normalModuleFactory);compilation.dependencyTemplates.set(HarmonyExportImportedSpecifierDependency,newHarmonyExportImportedSpecifierDependency.Template());compilation.dependencyFactories.set(HarmonyAcceptDependency,newNullFactory());compilation.dependencyTemplates.set(HarmonyAcceptDependency,newHarmonyAcceptDependency.Template());compilation.dependencyFactories.set(HarmonyAcceptImportDependency,normalModuleFactory);compilation.dependencyTemplates.set(HarmonyAcceptImportDependency,newHarmonyAcceptImportDependency.Template());consthandler=(parser,parserOptions)=>{if(parserOptions.harmony!==undefined&&!parserOptions.harmony)return;newHarmonyDetectionParserPlugin().apply(parser);newHarmonyImportDependencyParserPlugin(this.options).apply(parser);newHarmonyExportDependencyParserPlugin(this.options).apply(parser);newHarmonyTopLevelThisParserPlugin().apply(parser);};normalModuleFactory.hooks.parser.for("javascript/auto").tap("HarmonyModulesPlugin",handler);normalModuleFactory.hooks.parser.for("javascript/esm").tap("HarmonyModulesPlugin",handler);});}}module.exports=HarmonyModulesPlugin;
在 HarmonyModulesPlugin 引入的文件当中主要是分为了2部分:
ES Module 当中使用的不同语法的依赖类型
ES Module 使用的不同的依赖语法,在代码通过 parser 编译过程中需要挂载的 hooks(这些 hooks 都是通过相关 plugin 进行注册),方便做依赖收集
webpack 对于不同依赖模块的模板处理都有单独的依赖模块类型文件来进行处理。例如,在你写的源代码当中,使用的是ES Module,那么最终会由 HarmonyModulesPlugin 里面使用的依赖进行处理,再例如你写的源码中模块使用的是符合 CommonJS Module 规范,那么最终会有 CommonJsPlugin 里面使用的依赖进行处理。除此外,webpack 还对于其他类型的模块依赖语法也做了处理:
模块依赖语法的处理对于 webpack 生成最终的文件内容非常的重要。这些针对不同依赖加载语法的处理插件在 webpack 初始化创建 compiler 的时候就完成了加载及初始化过程。这里我们可以来看下模块遵循 ES Module 所使用的相关的依赖依赖模板的处理是如何进行的,即 HarmonyModulesPlugin 这个插件内部主要完成的工作。
在 HarmonyModulesPlugin 引入的文件当中主要是分为了2部分:
当 webpack 创建新的 compilation 对象后,便执行
compiler.hooks.compilation
注册的钩子内部的方法。其中主要完成了以下几项工作:1.设置不同依赖类型的 moduleFactory,例如设置
HarmonyImportSpecifierDependency
依赖类型的 moduleFactory 为normalModuleFactory
;2.设置不同依赖类型的 dependencyTemplate,例如设置
HarmonyImportSpecifierDependency
依赖类型的模板为new HarmonyImportSpecifierDependency.Template()
实例;3.注册 normalModuleFactory.hooks.parser 钩子函数。每当新建一个 normalModule 时这个钩子函数都会被执行,即触发 handler 函数的执行。handler 函数内部去初始化各种 plugin,注册相关的 hooks。
我们首先来看下 handler 函数内部初始化的几个 plugin 里面注册的和 parser 编译相关的插件。
HarmonyDetectionParserPlugin
在每个 module 开始编译的时候便会触发这个 plugin 上注册的 hooks。通过 AST 的节点类型来判断这个 module 是否是 ES Module,如果是的话,首先会实例化一个
HarmonyCompatibilityDependency
依赖的实例,并记录依赖需要替换的位置,然后将这个实例加入到 module 的依赖中,接下来实例化一个HarmonyInitDependency
依赖的实例,并记录依赖需要替换的位置,然后将实例加入到 module 的依赖当中。然后会设定当前被 parser 处理的 module 最终被渲染时的一些构建信息,例如exportsArgument
可能会使用__webpack_exports__
,即这个模块输出挂载变量使用__webpack_exports__
。其中
HarmonyCompatibilityDependency
依赖的 Template 主要是:调用 RuntimeTemplate 实例上提供的 defineEsModuleFlagStatement 方法在当前模块最终生成的代码内插入代码:
而在
HarmonyInitDependency
依赖的 Template 中主要完成的工作是:HarmonyImportDependencyParserPlugin
接下来我们再来看 HarmonyModulesPlugin 插件里面初始化的第二个插件
HarmonyImportDependencyParserPlugin
,这个插件主要完成的工作是和 ES Module 当中使用 import 语法相关:在这个插件里面主要是注册了在模块通过 parser 编译的过程中,遇到不同 tokens 触发的 hooks。例如
hooks.importSpecifier
主要是用于你通过import
语法加载其他模块时所申明的变量名,会通过一个 map 结构记录这个变量名。当你在源代码中使用了这个变量名,例如作为一个函数去调用(对应触发hooks.call
钩子),或者是作为一个表达式去访问(对应触发hooks.express
钩子),那么它们都会新建一个HarmonyImportSpecifierDependency
依赖的实例,并进入到当前被编译的 module 当中。这个
HarmonyImportSpecifierDependency
模板依赖主要完成的工作就是:将源码中引入的其他模块的依赖变量名进行字符串的替换,具体可以查阅
RuntimeTemplate.exportFromImport
方法。我们来看个例子:
HarmonyExportDependencyParserPlugin
这个插件主要完成的是和 ES Module 当中使用 export 语法相关的工作:
parse 在编译源码过程中,根据你使用的不同的 ES Module export 语法去触发不通过的 hooks,然后给当前编译的 module 加入对应的依赖 module。还是通过2个例子来看:
具体替换的工作可以查阅
HarmonyExportSpecifierDependency.Template
和HarmonyExportImportedSpecifierDependency.Template
提供的依赖模板函数。The text was updated successfully, but these errors were encountered: