直接看人话总结html
承接上一章git
该文章项目地址github
文章地址typescript
欢迎看看个人类angular框架bootstrap
试读angular源码第一章:开场与platformBrowserDynamic数组
试读angular源码第二章:引导模块bootstrapModulepromise
试读angular源码第四章:angular模块及JIT编译模块缓存
NgModule
是一个带有 @NgModule
装饰器的类。
@NgModule
的参数是一个元数据对象,用于描述如何编译组件的模板,以及如何在运行时建立注入器。
它会标出该模块本身的组件、指令和管道,经过 exports
属性公开其中的一部分,以便外部组件使用它们。
NgModule
还能把一些服务提供商添加到应用的依赖注入器中。
在以前的例子中,咱们经过 platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));
引导初始化时,bootstrapModule
方法传入的第一个参数就是angular 模块 NgModule
。
这里咱们要先讲2个概念:JIT 和 AOT
Angular 提供了两种方式来编译你的应用:
JIT的流程
AOT的流程
.metadata.json
文件但这里咱们只讨论 JIT 模式!
angular/packages/core/src/metadata/ng_module.ts
export interface NgModuleDecorator {
(obj?: NgModule): TypeDecorator;
new (obj?: NgModule): NgModule;
}
export interface NgModule {
providers?: Provider[];
declarations?: Array<Type<any>|any[]>;
imports?: Array<Type<any>|ModuleWithProviders<{}>|any[]>;
exports?: Array<Type<any>|any[]>;
entryComponents?: Array<Type<any>|any[]>;
bootstrap?: Array<Type<any>|any[]>;
schemas?: Array<SchemaMetadata|any[]>;
id?: string;
jit?: true;
}
/** * @Annotation * @publicApi */
export const NgModule: NgModuleDecorator = makeDecorator(
'NgModule', (ngModule: NgModule) => ngModule, undefined, undefined,
/** * Decorator that marks the following class as an NgModule, and supplies * configuration metadata for it. * * * The `declarations` and `entryComponents` options configure the compiler * with information about what belongs to the NgModule. * * The `providers` options configures the NgModule's injector to provide * dependencies the NgModule members. * * The `imports` and `exports` options bring in members from other modules, and make * this module's members available to others. */
(type: NgModuleType, meta: NgModule) => SWITCH_COMPILE_NGMODULE(type, meta));
复制代码
装饰器 @NgModule
的做用是描述 angular 模块,并提供 元数据 支持
例如几个经常使用的元数据:
providers?: Provider[];
依赖注入系统提供可注入项的重点
providers
能够提供给全局任何指令管道服务,至关于 @Injectable
为 root
declarations
属于此模块的组件,指令和管道的集合imports
引入其余模块的 export
exports
处处给其余模块的 imports
bootstrap
引导用的入口组件,一般根模块和路由懒加载须要设置entryComponents
入口组件 不经常使用,angular 编译器会自动将 bootstrap
编译到里面而 @NgModule
由 makeDecorator
构造而来:
makeDecorator
用来建立 angular 装饰器,像 @NgModule
@Component
@Pipe
@Directive
都用改方法建立:
angular/packages/core/src/util/decorators.ts
export const ANNOTATIONS = '__annotations__';
export function makeDecorator<T>(
name: string,
props?: (...args: any[]) => any, // 注释:args 就是装饰器的参数用来处理装饰器参数
parentClass?: any,
additionalProcessing?: (type: Type<T>) => void, // 注释:额外的处理
typeFn?: (type: Type<T>, ...args: any[]) => void) // 注释:用来处理class的原型
: {new (...args: any[]): any; (...args: any[]): any; (...args: any[]): (cls: any) => any;} {
const metaCtor = makeMetadataCtor(props); // 注释:建立 Metadata 的构造函数
function DecoratorFactory(...args: any[]): (cls: Type<T>) => any {
if (this instanceof DecoratorFactory) { // 注释:经过 args 用来设置默认值
metaCtor.call(this, ...args); // 注释:this就是DecoratorFactory工厂,也就是参数对象
return this;
}
const annotationInstance = new (DecoratorFactory as any)(...args); // 注释:注解实例实际上就是装饰器的参数对象
return function TypeDecorator(cls: Type<T>) { // 注释:cls就是装饰器装饰的类构造函数
if (typeFn) typeFn(cls, ...args);
// Use of Object.defineProperty is important since it creates non-enumerable property which
// prevents the property is copied during subclassing.
const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
(cls as any)[ANNOTATIONS] :
Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS];
annotations.push(annotationInstance); // 注释:将装饰器的处理结果存在
if (additionalProcessing) additionalProcessing(cls);
return cls;
};
}
if (parentClass) {
DecoratorFactory.prototype = Object.create(parentClass.prototype); // 注释:使实例 DecoratorFactory 继承继承 parentClass
}
DecoratorFactory.prototype.ngMetadataName = name; // 注释:装饰器名称会被放在原型属性 ngMetadataName 上
(DecoratorFactory as any).annotationCls = DecoratorFactory;
return DecoratorFactory as any;
}
function makeMetadataCtor(props?: (...args: any[]) => any): any {
return function ctor(...args: any[]) {
if (props) {
const values = props(...args);
for (const propName in values) {
this[propName] = values[propName];
}
}
};
}
复制代码
参数:
name: string
就是装饰器的名称props?: (...args: any[]) => any
args
就是装饰器的参数,props
用来处理装饰器参数,可用于默认值设置parentClass?: any
父类,提供给 DecoratorFactory
实例用来继承additionalProcessing?: (type: Type<T>) => void
对类构造函数进行额外处理,参数是装饰器的宿主类的构造函数typeFn?: (type: Type<T>, ...args: any[]) => void)
在装饰器的返回函数中,会再次执行下回调函数,参数是类构造函数和参数在这里 makeDecorator
基本上作了这几个事情:
makeMetadataCtor
建立一个给类构造函数附加初始值的函数 ,本质上是建立 Metadata 的构造函数this
是注解工厂 DecoratorFactory
的实例,则经过上面给类构造函数附加初始值的函数,传入 this
和装饰器参数 args
typeFn
传入类构造函数和参数,修改类构造函数DecoratorFactory
的实例 ,注解工厂方法会递归执行,直到 this
是注解工厂 DecoratorFactory
的实例 (注解工厂 DecoratorFactory
的实例实际上就是装饰器的参数对象)__annotations__:any[]
属性,把装饰器处理结果(注解实例===参数对象)保存在类构造函数的 __annotations__:any[]
属性数组中,并提供给编译器 compiler
使用DecoratorFactory
的原型,继承父类 parentClass
并添加元数据的名字 ngMetadataName
注意这里:DecoratorFactory.prototype = Object.create(parentClass.prototype);
经过使用 Object.create
避免执行一次 parentClass
来继承父类
makeDecorator
的做用就是构造返回一个函数 DecoratorFactory
用做 装饰器,并建立装饰器工厂 DecoratorFactory
实例@NgModule
就是一个接受参数并返回函数的方法,装饰器会把 @NgModule
传入的元数据对象进行处理并生成注解工厂 DecoratorFactory
的实例挂在到 __annotations__:any
提供给编译器使用。划重点:AppModule.__annotations__
:
最后你们能够打印下 (AppModule as any).__annotations__
来进行验证,这就是存在模块类上的注解实例。
此处建议结合第二章bootstrapModule一块儿阅读
先看下以前构建的 JitCompilerFactory
时注入过的服务,这些在后面编译的时候会大量用到:
angular/packages/platform-browser-dynamic/src/compiler_factory.ts
/** * A set of providers that provide `JitCompiler` and its dependencies to use for * template compilation. */
export const COMPILER_PROVIDERS = <StaticProvider[]>[
// 注释:这里也是一个核心点-编译反射器
{provide: CompileReflector, useValue: new JitReflector()},
// 注释:ResourceLoader- 资源加载器
{provide: ResourceLoader, useValue: _NO_RESOURCE_LOADER},
// 注释:jit 摘要解析器
{provide: JitSummaryResolver, deps: []},
// 注释:摘要解析器
{provide: SummaryResolver, useExisting: JitSummaryResolver},
{provide: Console, deps: []},
// 注释:语法分析器
{provide: Lexer, deps: []},
// 注释:解析器器
{provide: Parser, deps: [Lexer]},
// 注释:基本的HTML解析器
{
provide: baseHtmlParser,
useClass: HtmlParser,
deps: [],
},
// 注释:国际化的HTML解析器
{
provide: I18NHtmlParser,
useFactory: (parser: HtmlParser, translations: string | null, format: string,
config: CompilerConfig, console: Console) => {
translations = translations || '';
const missingTranslation =
translations ? config.missingTranslation ! : MissingTranslationStrategy.Ignore;
// 注释:new 国际化的HTML解析器
return new I18NHtmlParser(parser, translations, format, missingTranslation, console);
},
deps: [
baseHtmlParser,
[new Optional(), new Inject(TRANSLATIONS)],
[new Optional(), new Inject(TRANSLATIONS_FORMAT)],
[CompilerConfig],
[Console],
]
},
{
provide: HtmlParser,
useExisting: I18NHtmlParser,
},
// 注释:模板解析器
{
provide: TemplateParser, deps: [CompilerConfig, CompileReflector,
Parser, ElementSchemaRegistry,
I18NHtmlParser, Console]
},
{ provide: JitEvaluator, useClass: JitEvaluator, deps: [] },
// 注释:指令规范器
{ provide: DirectiveNormalizer, deps: [ResourceLoader, UrlResolver, HtmlParser, CompilerConfig]},
// 注释:元数据解析器
{ provide: CompileMetadataResolver, deps: [CompilerConfig, HtmlParser, NgModuleResolver,
DirectiveResolver, PipeResolver,
SummaryResolver,
ElementSchemaRegistry,
DirectiveNormalizer, Console,
[Optional, StaticSymbolCache],
CompileReflector,
[Optional, ERROR_COLLECTOR_TOKEN]]},
DEFAULT_PACKAGE_URL_PROVIDER,
// 注释:样式编译器
{ provide: StyleCompiler, deps: [UrlResolver]},
// 注释:view 编译器
{ provide: ViewCompiler, deps: [CompileReflector]},
// 注释:NgModule编译器
{ provide: NgModuleCompiler, deps: [CompileReflector] },
// 注释:编译器配置项目
{ provide: CompilerConfig, useValue: new CompilerConfig()},
// 注释:JIT时,Compiler的服务供应商 CompilerImpl
{ provide: Compiler, useClass: CompilerImpl, deps: [Injector, CompileMetadataResolver,
TemplateParser, StyleCompiler,
ViewCompiler, NgModuleCompiler,
SummaryResolver, CompileReflector, JitEvaluator, CompilerConfig,
Console]},
// 注释:DOM schema
{ provide: DomElementSchemaRegistry, deps: []},
// 注释:Element schema
{ provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
// 注释:URL解析器
{ provide: UrlResolver, deps: [PACKAGE_ROOT_URL]},
// 注释:指令解析器
{ provide: DirectiveResolver, deps: [CompileReflector]},
// 注释:管道解析器
{ provide: PipeResolver, deps: [CompileReflector]},
// 注释:模块解析器
{ provide: NgModuleResolver, deps: [CompileReflector]},
];
复制代码
讲完了 @NgModule
,回到以前的文章,看下 bootstrapModule
这个方法如何编译模块:
angular/packages/core/src/application_ref.ts
let compileNgModuleFactory:
<M>(injector: Injector, options: CompilerOptions, moduleType: Type<M>) =>
Promise<NgModuleFactory<M>> = compileNgModuleFactory__PRE_R3__;
function compileNgModuleFactory__PRE_R3__<M>( injector: Injector, options: CompilerOptions, moduleType: Type<M>): Promise<NgModuleFactory<M>> {
const compilerFactory: CompilerFactory = injector.get(CompilerFactory);
const compiler = compilerFactory.createCompiler([options]);
return compiler.compileModuleAsync(moduleType);
}
@Injectable()
export class PlatformRef {
...
bootstrapModule<M>(moduleType: Type<M>, compilerOptions: (CompilerOptions&BootstrapOptions)| Array<CompilerOptions&BootstrapOptions> = []):Promise<NgModuleRef<M>> {
const options = optionsReducer({}, compilerOptions);
return compileNgModuleFactory(this.injector, options, moduleType)
.then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
}
...
}
复制代码
bootstrapModule
调用了 compileNgModuleFactory
这个方法,而最后其实在 JIT 模式下,其实是 coreDynamic
提供的 JitCompilerFactory
建立了 CompilerImpl
实例并建立了代理 JitCompiler
去实现真正的编译。
angular/packages/platform-browser-dynamic/src/compiler_factory.ts
export class CompilerImpl implements Compiler {
...
private _delegate: JitCompiler;
...
constructor( injector: Injector, private _metadataResolver: CompileMetadataResolver, templateParser: TemplateParser, styleCompiler: StyleCompiler, viewCompiler: ViewCompiler, ngModuleCompiler: NgModuleCompiler, summaryResolver: SummaryResolver<Type<any>>, compileReflector: CompileReflector, jitEvaluator: JitEvaluator, compilerConfig: CompilerConfig, console: Console) {
// 注释:建立 JIT 编译器
this._delegate = new JitCompiler(
_metadataResolver, templateParser, styleCompiler, viewCompiler, ngModuleCompiler,
summaryResolver, compileReflector, jitEvaluator, compilerConfig, console,
this.getExtraNgModuleProviders.bind(this));
}
compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> { // 注释:异步建立模块及其子组件
return this._delegate.compileModuleAsync(moduleType) as Promise<NgModuleFactory<T>>;
}
...
}
复制代码
最终由 JitCompiler
执行 compileModuleAsync
方法编译模块
编译模块和组件的实际工做是由 CompilerImpl
交由代理 JitCompiler
的方法 compileModuleAsync<T>(moduleType: Type<T>)
完成的:
angular/packages/compiler/src/jit/compiler.ts
export class JitCompiler {
private _compiledTemplateCache = new Map<Type, CompiledTemplate>();
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
private _compiledDirectiveWrapperCache = new Map<Type, Type>();
private _compiledNgModuleCache = new Map<Type, object>();
private _sharedStylesheetCount = 0;
private _addedAotSummaries = new Set<() => any[]>();
constructor(
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _ngModuleCompiler: NgModuleCompiler, private _summaryResolver: SummaryResolver<Type>,
private _reflector: CompileReflector, private _jitEvaluator: JitEvaluator,
private _compilerConfig: CompilerConfig, private _console: Console,
private getExtraNgModuleProviders: (ngModule: any) => CompileProviderMetadata[]) {
...
}
...
compileModuleAsync(moduleType: Type): Promise<object> {
// 注释:其实 JTI 编译在这步作的
return Promise.resolve(this._compileModuleAndComponents(moduleType, false));
}
// 注释:作了三件事:
// 1. 加载模块 `this._loadModules`
// 2. 编译入口组件 `this._compileComponents`
// 3. 编译模块 `this._compileModule`
private _compileModuleAndComponents(moduleType: Type, isSync: boolean): SyncAsync<object> {
// 注释:其实调用的是这步,编译主模块和组件
return SyncAsync.then(this._loadModules(moduleType, isSync), () => { // 注释:先加载模块
this._compileComponents(moduleType, null); // 注释:异步有结果以后的回调函数,编译主模块上的全部入口组件
return this._compileModule(moduleType); // 注释:返回编译后的模块工厂
});
}
...
}
复制代码
结合第二章引导模块总结下:
compileModuleAsync
在这里只作了三件事:
this._loadModules
this._compileComponents
this._compileModule
angular/packages/compiler/src/jit/compiler.ts
export class JitCompiler {
...
// 注释:异步加载解析主模块,也就是 bootstrap 的 ngModule
private _loadModules(mainModule: any, isSync: boolean): SyncAsync<any> {
const loading: Promise<any>[] = [];
// 注释:从元数据中得到根模块的 __annotations__ 并格式化
const mainNgModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
// 注释:过滤 AOT 模块并异步编加载数据中所有指令组件和和管道
// 注释:过滤掉根模块元数据中的 AOT 模块
this._filterJitIdentifiers(mainNgModule.transitiveModule.modules).forEach((nestedNgModule) => {
// getNgModuleMetadata only returns null if the value passed in is not an NgModule
const moduleMeta = this._metadataResolver.getNgModuleMetadata(nestedNgModule) !;
this._filterJitIdentifiers(moduleMeta.declaredDirectives).forEach((ref) => {
// 注释:异步编加载数据中所有指令组件和和管道
const promise =
this._metadataResolver.loadDirectiveMetadata(moduleMeta.type.reference, ref, isSync);
if (promise) {
loading.push(promise);
}
});
this._filterJitIdentifiers(moduleMeta.declaredPipes)
.forEach((ref) => this._metadataResolver.getOrLoadPipeMetadata(ref));
});
// 注释:最后所有并行 Promise
return SyncAsync.all(loading);
}
...
// 注释:过滤掉根模块元数据中的 AOT 模块
hasAotSummary(ref: Type) { return !!this._summaryResolver.resolveSummary(ref); }
// 注释:过滤掉根模块元数据中的 AOT 模块
private _filterJitIdentifiers(ids: CompileIdentifierMetadata[]): any[] {
return ids.map(mod => mod.reference).filter((ref) => !this.hasAotSummary(ref));
}
}
复制代码
_loadModules
接受2个参数:
mainModule: any
模块类isSync: boolean
是不是同步加载 在 bootstrapModule
的时候是 false
,异步加载_loadModules
作了什么?
this._metadataResolver.getNgModuleMetadata
获取到以前 makeDecorator
在模块类上建立的静态属性 __annotations__
并编译模块的元数据this._filterJitIdentifiers
递归过滤掉 AOT 模块this._metadataResolver.loadDirectiveMetadata(moduleMeta.type.reference, ref, isSync)
异步加载所有指令组件和和管道的元数据Promise
并返回异步编译的结果AppModule
关联的模块的元数据都已经加载进了缓存中,包括了从 AppModule
开始除了懒加载模块以外的的整个模块树,树上的全部指令,组件和管道,以及全部的服务。接下来继续看 _compileModuleAndComponents
在加载完模块以后,调用了 this._compileComponents
编译组件:
angular/packages/compiler/src/jit/compiler.ts
export class JitCompiler {
// 注释:作了三件事:
// 1. 加载模块 `this._loadModules`
// 2. 编译入口组件 `this._compileComponents`
// 3. 编译模块 `this._compileModule`
private _compileModuleAndComponents(moduleType: Type, isSync: boolean): SyncAsync<object> {
// 注释:其实调用的是这步,编译主模块和组件
return SyncAsync.then(this._loadModules(moduleType, isSync), () => { // 注释:先加载模块
this._compileComponents(moduleType, null); // 注释:异步有结果以后的回调函数,编译主模块上的全部入口组件
return this._compileModule(moduleType); // 注释:返回编译后的模块工厂
});
}
}
复制代码
_compileComponents
方法用来编译根模块组件的模板:
angular/packages/compiler/src/jit/compiler.ts
export class JitCompiler {
// 注释:编译主模块上的全部组件
// 主要目的:拿到被声明的组件的模板、入口组件的模板,最终拿到了全部涉及的模板,放在 templates 中
_compileComponents(mainModule: Type, allComponentFactories: object[]|null) {
// 注释:获取主模块
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
const moduleByJitDirective = new Map<any, CompileNgModuleMetadata>();
const templates = new Set<CompiledTemplate>();
// 注释:过滤AOT模块
const transJitModules = this._filterJitIdentifiers(ngModule.transitiveModule.modules);
// 注释:编译各个模块的模板,(localMod 是模块的class)
transJitModules.forEach((localMod) => {
const localModuleMeta = this._metadataResolver.getNgModuleMetadata(localMod) !;
// 注释:指令和组件都是 declaredDirectives (在angular里 @Component组件 继承了 指令@Directive)
this._filterJitIdentifiers(localModuleMeta.declaredDirectives).forEach((dirRef) => {
moduleByJitDirective.set(dirRef, localModuleMeta);
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirRef);
// 注释:只编译组件
// 注释:拿到全部的模板,并放在 templates:Set 中
if (dirMeta.isComponent) {
templates.add(this._createCompiledTemplate(dirMeta, localModuleMeta));
if (allComponentFactories) {
const template =
this._createCompiledHostTemplate(dirMeta.type.reference, localModuleMeta);
templates.add(template);
allComponentFactories.push(dirMeta.componentFactory as object);
}
}
});
});
// 注释:编译入口组件的模板
transJitModules.forEach((localMod) => {
const localModuleMeta = this._metadataResolver.getNgModuleMetadata(localMod) !;
this._filterJitIdentifiers(localModuleMeta.declaredDirectives).forEach((dirRef) => {
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirRef);
if (dirMeta.isComponent) {
dirMeta.entryComponents.forEach((entryComponentType) => {
const moduleMeta = moduleByJitDirective.get(entryComponentType.componentType) !;
templates.add(
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
});
}
});
localModuleMeta.entryComponents.forEach((entryComponentType) => {
if (!this.hasAotSummary(entryComponentType.componentType)) {
const moduleMeta = moduleByJitDirective.get(entryComponentType.componentType) !;
templates.add(
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
}
});
});
// 注释:执行 _compileTemplate 编译模板
templates.forEach((template) => this._compileTemplate(template));
}
}
复制代码
在这里主要作了下面这几件事:
this._metadataResolver.getNgModuleMetadata
像以前编译模板同样获取根模块this._filterJitIdentifiers
过滤 AOT 模块declarations
),并编译其模板entryComponents
),并编译其模板至于如何编译的模板,以后讲组件的时候再说吧。
_compileComponents
的目的是拿到被声明的组件的模板、入口组件的模板,最终拿到了全部涉及的模板
angular/packages/compiler/src/jit/compiler.ts
export class JitCompiler {
...
// 注释:angular 会用 Map 缓存模块工厂,而且在须要返回编译的模块工厂时,优先去缓存中寻找已经被编译过的模块工厂
private _compileModule(moduleType: Type): object {
// 注释:从缓存拿到模块工厂
let ngModuleFactory = this._compiledNgModuleCache.get(moduleType) !; // 注释:读取缓存
if (!ngModuleFactory) {
// 注释:读取模块的元数据
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType) !;
// 注释:调用实例化 JITCompiler 时候传入方法,建立额外的模块服务供应商 (在 CompilerImpl 传入)
// Always provide a bound Compiler
const extraProviders = this.getExtraNgModuleProviders(moduleMeta.type.reference);
// 注释:建立输出上下
const outputCtx = createOutputContext();
// 注释:构建编译结果:是一个对象,只有 ngModuleFactoryVar 这么一个属性:ngModuleFactoryVar: "AppModuleNgFactory",内部经过构建服务供应商和模块的AST,很复杂
const compileResult = this._ngModuleCompiler.compile(outputCtx, moduleMeta, extraProviders);
console.log(77777, moduleType, compileResult);
// 注释:动态建立出一个模块的工厂方法
ngModuleFactory = this._interpretOrJit(
ngModuleJitUrl(moduleMeta), outputCtx.statements)[compileResult.ngModuleFactoryVar];
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
}
return ngModuleFactory;
}
...
}
复制代码
这里也很简单:
JITCompiler
时候传入方法,建立额外的模块服务供应商 (在 CompilerImpl
传入)ngModuleFactoryVar
这么一个属性,估计是把编译结果放缓存了:ngModuleFactoryVar: "AppModuleNgFactory"
模块编译器这里比较复杂:
angular/packages/compiler/src/ng_module_compiler.ts
export class NgModuleCompiler {
constructor(private reflector: CompileReflector) {}
compile(
ctx: OutputContext, ngModuleMeta: CompileNgModuleMetadata,
extraProviders: CompileProviderMetadata[]): NgModuleCompileResult {
// 注释:生成一个关于模块类及文件位置的对象
const sourceSpan = typeSourceSpan('NgModule', ngModuleMeta.type);
// 注释:得到入口组件的工厂函数,默认就有 <ng-component/> 和 <app-root/>
const entryComponentFactories = ngModuleMeta.transitiveModule.entryComponents;
const bootstrapComponents = ngModuleMeta.bootstrapComponents;
// 注释:分析模块及模块引入的模块的服务供应商
const providerParser =
new NgModuleProviderAnalyzer(this.reflector, ngModuleMeta, extraProviders, sourceSpan);
// 注释:这块是AST了,生成了模块中全部服务供应商的函数 AST
const providerDefs =
[componentFactoryResolverProviderDef(
this.reflector, ctx, NodeFlags.None, entryComponentFactories)]
.concat(providerParser.parse().map((provider) => providerDef(ctx, provider)))
.map(({providerExpr, depsExpr, flags, tokenExpr}) => {
return o.importExpr(Identifiers.moduleProviderDef).callFn([
o.literal(flags), tokenExpr, providerExpr, depsExpr
]);
});
// 注释:这块是AST了,生成了模块的 AST
const ngModuleDef = o.importExpr(Identifiers.moduleDef).callFn([o.literalArr(providerDefs)]);
const ngModuleDefFactory = o.fn(
[new o.FnParam(LOG_VAR.name !)], [new o.ReturnStatement(ngModuleDef)], o.INFERRED_TYPE);
// 注释:建立一个字符串
const ngModuleFactoryVar = `${identifierName(ngModuleMeta.type)}NgFactory`;
// 注释:保存在上下文中声明中
this._createNgModuleFactory(
ctx, ngModuleMeta.type.reference, o.importExpr(Identifiers.createModuleFactory).callFn([
ctx.importExpr(ngModuleMeta.type.reference),
o.literalArr(bootstrapComponents.map(id => ctx.importExpr(id.reference))),
ngModuleDefFactory
]));
if (ngModuleMeta.id) {
const id = typeof ngModuleMeta.id === 'string' ? o.literal(ngModuleMeta.id) :
ctx.importExpr(ngModuleMeta.id);
const registerFactoryStmt = o.importExpr(Identifiers.RegisterModuleFactoryFn)
.callFn([id, o.variable(ngModuleFactoryVar)])
.toStmt();
// 注释:保存在上下文中
ctx.statements.push(registerFactoryStmt);
}
// 注释:返回编译结果
return new NgModuleCompileResult(ngModuleFactoryVar);
}
...
}
复制代码
这里作了下面几件事情:
<ng-component/>
和 <app-root/>
其实我没太看懂为何要转换为 AST,这里面留几个坑
总结下 @NgModule
大概发生了什么
makeDecorator
生成 @NgModule
注解@NgModule
经过传入的参数和反射,生成注解附加在模块类的静态属性 __annotations__
并提供给 JitCompiler
编译器使用bootstrapModule
被调用时候,在 JIT 模式下建立了代理 JitCompiler
去实现真正的编译JitCompiler
编译模块调用了 compileModuleAsync
并返回模块工厂,而且只作了三件事:
this._loadModules
this._compileComponents
this._compileModule