分析启动过程无非就是两件事:
- 加载了哪个启动页面和脚本
- 启动脚本干了什么事
下面分步骤进行记录。
-
加载了哪个启动页面和脚本
在执行npm start
命令之后会首先读取package.json文件,寻找其中关于start命令的定义,如下所示
找到之后便会执行start中的语句进行启动,也就是说npm start
命令和执行ng serve --proxy-config proxy.conf.json --port 4201
这一坨命令的效果是完全一样的。从这里开始,ng命令开始接管启动过程。
首先寻找应用目录下angular.json文件(不同Angular版本文件名略有差异,此处使用Angular 6.1.2),寻找图中所示的两行
index条目指明了启动时的加载页面,为src/index.html;main条目指明了启动时的加载脚本,为src/main.ts。
通常情况这些内容是Angular 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';
//配置环境中读取,如果是生产环境则关闭Angular的开发者模式
if (environment.production) {
enableProdMode();
}
/**
* 这里是程序主入口,相当于java中的main方法
* bootstrapModule的传入参数即为主启动模块,默认为AppModule,然后将产生的异常输出至控制台
**/
platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.log(err));
再来看AppModule里面做了什么事,转至文件app.module.ts
import {NgModule, APP_INITIALIZER, enableProdMode} from '@angular/core';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
......
@NgModule({
imports: [
//Angular会自动加载imports中声明的所有模块并加载,此过程是递归进行的,直至加载完最后一个模块
NoopAnimationsModule,
NavAsideModule,
......
],
declarations: [
AppComponent,
],
providers: [],
entryComponents: [],
//这里指定了启动组件,由于当前模块为主启动模块,此处声明的启动组件即为主启动组件,随后程序进入其中
bootstrap: [AppComponent]
})
export class AppModule {
}
接下来看AppComponent,转至文件app.component.ts
import { Component } from '@angular/core';
@Component({
//当前组件对应的css选择器
selector: 'app-root',
//对应的html模板
templateUrl: './app.component.html',
//对应的样式表
styleUrls: ['./app.component.css']
})
export class AppComponent {
}
这里做了什么事暂时还看不出来,先来看index.html,这里只摘取最重要的一部分
<html>
......
<body>
......
<app-root>Loading</app-root>
</body>
</html>
重点来了,此处app-root标签即为AppComponent组件所对应的CSS选择器的标签名。
在Angular尚未完全加载所有组件时,页面展示的内容为app-root中已有内容,本示例会显示Loading字样。在组件全部加载完成之后会将AppComponent组件中指定的html模板,即app.component.html中的内容替换掉app-root标签内已有的内容。至此Angular应用启动完成。
再来整理一下:
读取angular.json配置文件=》寻找index.html和main.ts=》
mian.ts中寻找bootstrapModule方法,分析方法入参AppModule=》
app.module.ts中分析imports所引用的其他模块,并递归加载=》
app.module.ts中寻找bootstrap所标记的主启动组件,分析AppComponent=》
app.component.ts中分析该组件对应的CSS选择器,html模板及样式表=》
在index.html中寻找主启动组件对应的标签app-root,并在Angular加载过程中渲染标签内的代码进行展示=》
全部组件加载完成之后,使用主启动组件AppComponent所对应的html模板中的内容替换掉标签app-root中原有的内容=》
加载完成