cli生成项目后,main.ts中的代码

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app/app.module';
import { environment } from './environments/environment';if (environment.production) {enableProdMode();
}platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));

这里调用了@angular/platform-browser-dynamic包中导出的platformBrowserDynamic函数,这个函数是浏览器平台的工厂函数,执行会返回浏览器平台的实例

export const platformBrowserDynamic = createPlatformFactory(platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS);

platformBrowserDynamic函数是通过createPlatformFactory函数创建的,这个函数接收3个参数,parentPlatformFactory(父平台工厂函数),name(平台名称),providers(服务提供商的数组)
<!-- 顾名思义,createPlatformFactory函数的作用是创建平台工厂的函数 -->

export function createPlatformFactory(parentPlatformFactory: ((extraProviders?: StaticProvider[]) => PlatformRef) | null,name: string, providers: StaticProvider[] = []): (extraProviders?: StaticProvider[]) =>PlatformRef {const desc = `Platform: ${name}`;const marker = new InjectionToken(desc);return (extraProviders: StaticProvider[] = []) => {let platform = getPlatform();if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {if (parentPlatformFactory) {parentPlatformFactory(providers.concat(extraProviders).concat({provide: marker, useValue: true}));} else {const injectedProviders: StaticProvider[] =providers.concat(extraProviders).concat({provide: marker, useValue: true});createPlatform(Injector.create({providers: injectedProviders, name: desc}));}}return assertPlatform(marker);};
}

在angular框架被加载后,会执行这个函数,并传入了三个参数分别为 platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS

看第一个参数platformCoreDynamic:

export const platformCoreDynamic = createPlatformFactory(platformCore, 'coreDynamic', [{provide: COMPILER_OPTIONS, useValue: {}, multi: true},{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
]);

第一个参数也是通过createPlatformFactory函数创建的一个工厂函数,这里执行的时候又传入了三个参数platformCore,'coreDynamic'和一个提供商数组

第一个参数platformCore:

export const platformCore = createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS);

又是通过createPlatformFactory函数创建的... ,但好在没有在继续传入父平台作为参数,所以应用初始化时执行的第一个函数就是这个了

这里有点绕,屡一下函数的执行过程:

  • createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS)执行返回platformCore函数
  • createPlatformFactory(platformCore, 'coreDynamic', [...])执行返回platformCoreDynamic函数
  • createPlatformFactory(platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS)执行返回platformBrowserDynamic函数
  • platformBrowserDynamic()执行返回平台实例

要注意到这里创建的都是工厂函数,而不是平台实例,在angular框架被加载后,就会开始执行,此时应用还没有正式启动

在执行platformBrowserDynamic()后,应用开始启动,实例化core平台(这里的调用顺序就不贴出来了,虽然工厂函数的调用顺序是platformBrowserDynamic->platformCoreDynamic->platformCore,但是实例化的只有core平台)

coreDynamic平台和browserDynamic平台的工厂函数并不是创建子平台的实例,而是添加服务提供商,被实例化的只有一个平台实例,只不过会改变PLATFORM_IDtoken的值

core平台实例化之前,首先创建了应用的根注入器

createPlatform(Injector.create({providers: injectedProviders, name: desc}));

core平台实例化过程中,又通过子平台工厂函数的参数和区域变量,传入了一些服务提供商,然后将这些提供商统一注册到了注入器中:

// 这里的变量名是我命名的不是源码中的名字,用以区分各个平台下注册的提供商
export const browserDynamic_PROVIDERS: StaticProvider[] = [{provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID},{provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true},{provide: PlatformLocation, useClass: BrowserPlatformLocation, deps: [DOCUMENT]},{provide: DOCUMENT, useFactory: _document, deps: []},{provide: COMPILER_OPTIONS,useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: []}]},multi: true},{provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID}
];export const coreDynamic_PROVIDERS: StaticProvider[] = [{provide: COMPILER_OPTIONS, useValue: {}, multi: true},{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]}
];export const core_PROVIDERS: StaticProvider[] = [// Set a default platform name for platforms that don't set it explicitly.{provide: PLATFORM_ID, useValue: 'unknown'},{provide: PlatformRef, deps: [Injector]},{provide: TestabilityRegistry, deps: []},{provide: Console, deps: []},
]

然后进行初始化的操作,包括BrowserDomAdapter(DOM适配器)和BrowserGetTestability

export function createPlatform(injector: Injector): PlatformRef {if (_platform && !_platform.destroyed &&!_platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {throw new Error('There can be only one platform. Destroy the previous one to create a new one.');}_platform = injector.get(PlatformRef);// 初始化操作 browserDynamic平台下的PLATFORM_INITIALIZER服务const inits = injector.get(PLATFORM_INITIALIZER, null);if (inits) inits.forEach((init: any) => init());return _platform;
}

这里初始化操作是通过PLATFORM_INITIALIZERtoken注入,然后遍历执行,所以也可以在应用中注入PLATFORM_INITIALIZER,然后执行一些启动时的自定义的任务.

到这里,core平台的实例化就完成了.

ps:

除了platform-browser-dynamic之外还有platform-browser模块,这两个模块的区别是编译方式的不同,platform-browser-dynamic模块提供jit编译,也就是说编译在浏览器内完成,而platform-browser模块提供aot编译,编译在本地完成.

在代码层面上来说,platform-browser模块下core平台的子平台只有browser平台,而platform-browser-dynamic模块下,core平台的子平台包含coreDynamic平台和browserDynamic平台,并添加了额外的服务提供商

  {provide: COMPILER_OPTIONS,useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: []}]},multi: true},{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},

angular源码分析之platformBrowserDynamic相关推荐

  1. 试读angular源码第三章:初始化zone

    直接看人话总结 前言 承接上一章 项目地址 文章地址 angular 版本:8.0.0-rc.4 欢迎看看我的类angular框架 文章列表 试读angular源码第一章:开场与platformBro ...

  2. 【转】ABP源码分析三十七:ABP.Web.Api Script Proxy API

    ABP提供Script Proxy WebApi为所有的Dynamic WebApi生成访问这些WebApi的JQuery代理,AngularJs代理以及TypeScriptor代理.这些个代理就是j ...

  3. qiankun 2.x 运行时沙箱 源码分析

    当学习成为了习惯,知识也就变成了常识.感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github,欢迎 Watch 和 Star. 简介 ...

  4. UnityStandardAsset工程、源码分析_5_赛车游戏[AI控制]_AI机制

    上一章地址: UnityStandardAsset工程.源码分析_4_赛车游戏[玩家控制]_摄像机控制 前几章我们已经将赛车游戏的绝大多数机制分析过了,而Unity还提供了不同的操控模式--AI控制. ...

  5. UnityStandardAsset工程、源码分析_4_赛车游戏[玩家控制]_摄像机控制

    上一章地址:UnityStandardAsset工程.源码分析_3_赛车游戏[玩家控制]_特效.声效 经过前几章的分析,我们已经大致地了解了车辆控制相关的脚本.现在还有最后一个与玩家体验息息相关的部分 ...

  6. 微前端框架 之 qiankun 从入门到源码分析

    当学习成为了习惯,知识也就变成了常识.感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github,欢迎 Watch 和 Star. 简介 ...

  7. SingleSpa及qiankun入门、源码分析及案例

    文章目录 SingleSpa及qiankun入门.源码分析及案例 一.简介 1.微服务 2.什么是微前端 3.微前端的优点 4.微前端的缺点 5.如何落地微前端 6.示例 7.总结 二.SingleS ...

  8. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  9. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

最新文章

  1. LDO和DC-DC有什么不同?如何选型?
  2. 我说分布式事务之消息最终一致性事务(一):原理及实现
  3. PageRank算法--从原理到实现
  4. 分布式锁原理——redis分布式锁,zookeeper分布式锁
  5. 安装慢_Origin平台安装更新慢的解决办法
  6. 推荐一款好用的redis客户端工具
  7. sql 指定数据库中的信息操作
  8. 如何分享文件_分布式文件存储系统如何分享文件
  9. Tools: geos 使用指南
  10. python格式输出占四列左对齐_python – 打印字符串左对齐,固定宽度和后缀
  11. java guava map_使用googled的guava常见ImmutableMap、Multimap、Sets、Optional、Objects及Preconditions检查等用法...
  12. 检测air运行环境版本
  13. 用gcc3.4.5编译c++项目
  14. sql server 2012 数据库还原方法
  15. JS双引号替换单引号
  16. python环境window系统安装pyHook3
  17. 上海计算机在职专业硕士学校,2020年上海地区专业硕士招生院校大全
  18. Java实现判断是否参加上秒杀活动
  19. linux上ssh免密登录原理及实现
  20. 人工神经网络与神经网络,消息传递神经网络

热门文章

  1. POJ 3254 Corn Fields [DP]
  2. JZOJ 3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll)
  3. MapReduce 工作原理
  4. [Robot Framework] 怎么写动态等待?
  5. Java语法基础,课后实践
  6. Lintcode: Permutation Index
  7. JavaScript:windows关机效果
  8. iOS 10.3下解决Fiddler代理抓包ssl证书信任问题
  9. spring使用@Value注解读取.properties文件时出现中文乱码问题的解决
  10. 【推荐实践】因果推断在阿里文娱用户增长中的应用