作為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