深度解析@angular/platform-browser-dynamic

楊明明發表於2019-02-28

作為angular應用的入口模組,瞭解他的重要性是顯而易見的!今天閒來無事,便翻看@angular/platform-browser-dynamic原始碼,特此總結!希望觀看過本篇文章對您有用!

main.ts是這個樣子的,下面我就去解開platformBrowserDynamic神祕面紗!

import { platformBrowserDynamic } from `iwe7/platform-browser-dynamic`;
platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.log(err));
複製程式碼

platformBrowserDynamic原始碼

export const platformBrowserDynamic = createPlatformFactory(
  platformCoreDynamic,
  // 名字
  `browserDynamic`,
  // 注入所用到的服務
  INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS
);
複製程式碼

platformCoreDynamic原始碼

export const platformCoreDynamic = createPlatformFactory(
  // @angular/core
  platformCore,
  // 名字
  `coreDynamic`,
  [
    // 配置編譯專案
    { provide: COMPILER_OPTIONS, useValue: {}, multi: true },
    {
      // 自定義jit編譯工廠類,替換或實現原有的CompilerFactory,那麼核心應該在這裡了!!
      provide: CompilerFactory,
      useClass: JitCompilerFactory,
      deps: [COMPILER_OPTIONS]
    }
  ]
);
複製程式碼

通過檢視原始碼,去偽存真,發現了他的核心JitCompilerFactory,下面看下JitCompilerFactory這個類

JitCompilerFactory原始碼,核心發放是createCompiler

export class JitCompilerFactory implements CompilerFactory {
  private _defaultOptions: CompilerOptions[];

  /* @internal */
  constructor(defaultOptions: CompilerOptions[]) {
    const compilerOptions: CompilerOptions = {
      useJit: true,
      // 配置試圖
      defaultEncapsulation: ViewEncapsulation.Emulated,
      missingTranslation: MissingTranslationStrategy.Warning
    };
    this._defaultOptions = [compilerOptions, ...defaultOptions];
  }
  createCompiler(options: CompilerOptions[] = []): Compiler {
    const opts = _mergeOptions(this._defaultOptions.concat(options));
    const injector = Injector.create([
      // 建立Compiler的核心
      COMPILER_PROVIDERS,
    ]);
    return injector.get(Compiler);
  }
}
複製程式碼

發現核心關鍵COMPILER_PROVIDERS,順藤摸瓜,找到了@angular/platform-browser-dynamic的核心

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: 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] },
  // ng module編譯器
  { provide: NgModuleCompiler, deps: [CompileReflector] },
  // 編譯器配置專案
  { provide: CompilerConfig, useValue: new CompilerConfig() },
  {
    // 編譯器注入
    provide: Compiler,
    // 這裡也是一個核心
    useClass: CompilerImpl,
    deps: [
      Injector,
      CompileMetadataResolver,
      TemplateParser,
      StyleCompiler,
      ViewCompiler,
      NgModuleCompiler,
      SummaryResolver,
      CompileReflector,
      CompilerConfig,
      Console
    ]
  },
  // dom schema 
  { provide: DomElementSchemaRegistry, deps: [] },
  // element schema
  { provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry },
  // url 解析
  { provide: UrlResolver, deps: [PACKAGE_ROOT_URL] },
  // dirctive 解析
  { provide: DirectiveResolver, deps: [CompileReflector] },
  // pipe 解析
  { provide: PipeResolver, deps: [CompileReflector] },
  // ng module 解析
  { provide: NgModuleResolver, deps: [CompileReflector] }
];
複製程式碼

下面看看他的另外兩個核心

  • JitReflector
  • CompilerImpl

JitReflector

export class JitReflector implements CompileReflector {
  private reflectionCapabilities: ReflectionCapabilities;
  constructor() {
    // @angular/core -> ɵReflectionCapabilities
    this.reflectionCapabilities = new ReflectionCapabilities();
  }
  parameters(typeOrFunc: any): any[][] {
    return this.reflectionCapabilities.parameters(typeOrFunc);
  }
  annotations(typeOrFunc: any): any[] {
    return this.reflectionCapabilities.annotations(typeOrFunc);
  }
  shallowAnnotations(typeOrFunc: any): any[] {
    throw new Error(`Not supported in JIT mode`);
  }
  tryAnnotations(typeOrFunc: any): any[] {
    return this.annotations(typeOrFunc);
  }
  propMetadata(
    typeOrFunc: any
  ): {
    [key: string]: any[];
  } {
    return this.reflectionCapabilities.propMetadata(typeOrFunc);
  }
  // 解析生命週期鉤子
  hasLifecycleHook(type: any, lcProperty: string): boolean {
    return this.reflectionCapabilities.hasLifecycleHook(type, lcProperty);
  }
  guards(
    typeOrFunc: any
  ): {
    [key: string]: any;
  } {
    return this.reflectionCapabilities.guards(typeOrFunc);
  }
  // 元件url
  componentModuleUrl(type: any, cmpMetadata: Component): string {
    const moduleId = cmpMetadata.moduleId;
    if (typeof moduleId === `string`) {
      const scheme = getUrlScheme(moduleId);
      return scheme ? moduleId : `package:${moduleId}${MODULE_SUFFIX}`;
    } else if (moduleId !== null && moduleId !== void 0) {
      throw syntaxError(
        `moduleId should be a string in "${stringify(type)}". `
      );
    }
    return `./${stringify(type)}`;
  }
  resolveExternalReference(ref: ExternalReference): any {
    return builtinExternalReferences.get(ref) || ref.runtime;
  }
}


複製程式碼

CompilerImpl

export class CompilerImpl implements Compiler {
  private _delegate: JitCompiler;
  public readonly injector: Injector;
  constructor(
    injector: Injector,
    private _metadataResolver: CompileMetadataResolver,
    templateParser: TemplateParser,
    styleCompiler: StyleCompiler,
    viewCompiler: ViewCompiler,
    ngModuleCompiler: NgModuleCompiler,
    summaryResolver: SummaryResolver<Type<any>>,
    compileReflector: CompileReflector,
    compilerConfig: CompilerConfig,
    console: Console
  ) {
    this._delegate = new JitCompiler(
      _metadataResolver,
      templateParser,
      styleCompiler,
      viewCompiler,
      ngModuleCompiler,
      summaryResolver,
      compileReflector,
      compilerConfig,
      console,
      this.getExtraNgModuleProviders.bind(this)
    );
    this.injector = injector;
  }

  private getExtraNgModuleProviders() {
    return [
      this._metadataResolver.getProviderMetadata(
        new ProviderMeta(Compiler, { useValue: this })
      )
    ];
  }
  // 懶載入了,應該是
  compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> {
    return this._delegate.compileModuleSync(moduleType) as NgModuleFactory<T>;
  }
  compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> {
    return this._delegate.compileModuleAsync(moduleType) as Promise<
      NgModuleFactory<T>
    >;
  }
  compileModuleAndAllComponentsSync<T>(
    moduleType: Type<T>
  ): ModuleWithComponentFactories<T> {
    const result = this._delegate.compileModuleAndAllComponentsSync(moduleType);
    return {
      ngModuleFactory: result.ngModuleFactory as NgModuleFactory<T>,
      componentFactories: result.componentFactories as ComponentFactory<any>[]
    };
  }
  compileModuleAndAllComponentsAsync<T>(
    moduleType: Type<T>
  ): Promise<ModuleWithComponentFactories<T>> {
    return this._delegate
      .compileModuleAndAllComponentsAsync(moduleType)
      .then(result => ({
        ngModuleFactory: result.ngModuleFactory as NgModuleFactory<T>,
        componentFactories: result.componentFactories as ComponentFactory<any>[]
      }));
  }
  loadAotSummaries(summaries: () => any[]) {
    this._delegate.loadAotSummaries(summaries);
  }
  hasAotSummary(ref: Type<any>): boolean {
    return this._delegate.hasAotSummary(ref);
  }
  getComponentFactory<T>(component: Type<T>): ComponentFactory<T> {
    return this._delegate.getComponentFactory(component) as ComponentFactory<T>;
  }
  clearCache(): void {
    this._delegate.clearCache();
  }
  clearCacheFor(type: Type<any>) {
    this._delegate.clearCacheFor(type);
  }
}

複製程式碼

下面除錯一下前面分析的幾個核心,我就不分順序了。

JitReflector->hasLifecycleHook

生命週期檢測!

JitReflector->guards

路由守衛

JitReflector->componentModuleUrl

獲取componentModule的路徑,如: ./AppComponent

CompilerImpl->compileModuleSync

非同步編譯模組

CompilerImpl->compileModuleAsync

非同步編譯模組

CompilerImpl->compileModuleAndAllComponentsSync

編譯模組下的component

CompilerImpl->compileModuleAndAllComponentsAsync

非同步編譯模組下的component

CompilerImpl->getComponentFactory

獲取ComponentFactory例項

專案啟動後可以儲存專案例項,以便不時只需!

declare const window: any;

let ref1 = platformBrowserDynamic([])
  .bootstrapModule(AppModule)
  .then(res => {
    window.meepo = res;
  })
  .catch(err => console.log(err));
複製程式碼

總結

ng的程式碼寫的蠻規範的,閒來無事可以翻閱!以上程式碼僅是摘錄!具體可看@angular/platform-browser-dynamic

相關文章