Bootstrapping an Application in Angular
Jul 26, 2020 • 7 Minute Read
Introduction
The process of loading the index.html page, app-level module, and app-level component is called bootstrapping, or loading the app. In this guide, you will learn about the internals of the bootstrapping process.
Angular takes the following steps to bootstrap the application:
- Load index.html
- Load Angular, Other Libraries, and App Code
- Execute main.ts File
- Load App-Level Module
- Load App-Level Component
- Process Template
Load index.html
The starting point of any Angular web application is the index.html page. This page refers to all the necessary JavaScript files for the application. If you examine the index.html file after building an Angular project, you will find that it has references to the JavaScript files, as shown below:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GettingStarted</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="styles-es2015.js" type="module"></script>
<script src="styles-es5.js" nomodule defer></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule defer></script></body>
</html>
You will notice that there are two versions of each file:
- es2015
- es5
main.js has the application code in it.
Execute main.js Code
The code inside the main.js file is the entry point for the application. This file imports the module platformBrowserDynamic from the library @angular/platform-browser-dynamic. platformBrowserDynamic is the module responsible for loading the Angular app in the desktop browser. Similar to this module, the module platformNativeScriptDynamic loads the app in a mobile device. Angular is flexible enough to run in a browser, server, web-worker, or mobile device.
When bootstrapModule(AppModule, options) is called, it compiles the AppModule in the first step.
The code for the bootstrapModule function is as follows:
bootstrapModule<M>(moduleType: Type<M>, options: CompilerOptions): Promise<NgModuleRef<M>> {
return compileNgModuleFactory(this.injector, options, moduleType)
.then((moduleFactory: NgModuleFactory) => {
// ...
});
}
You will notice that the bootstrapModule is calling compileNgModuleFactory, which has the following code:
function compileNgModuleFactory<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);
}
First of all, it retrieves an instance of CompilerFactory from the injector. CompilerFactory is an abstract class that is responsible for the creation of an instance of the compiler. If the Angular app is running in dev mode, then an instance of JitCompiler is created that has the following code:
export class JitCompiler {
private compileModuleAsync(moduleType: Type): Promise<NgModuleFactory> {
return this._loadModules(moduleType)
.then(() => {
this._compileComponents(moduleType);
return this._compileModule(moduleType);
});
}
}
You will notice that it is loading all the modules, directives, and pipes metadata. Then, it compiles all the components. During the compilation of the components, it searches for all component metadata registered in the app and asks the compiler to compile all component templates in one place. The last thing it does is to actually compile the app-level module. At this stage, Angular resolves all the required metadata for the module and returns the module factory.
Before bootstrapping the Angular app, platformBrowserDynamic needs to create a root NgZone. Root NgZone has to be instantiated even before AppModule creation, because all the app logic has to be wrapped inside the root zone.
When the root NgZone creation is complete, the platformBrowserDynamic instantiates the app-level module through the root module factory created as a result of the module compilation step.
Every Angular app has at least one module. The module that is loaded first when the app is loaded is called the app-level module or root module. platformBrowserDynamic bootstraps the app-level module by invoking the bootstrapModule function and giving it the reference to your app-level module, i.e AppModule.
Load App-Level Module
The app-level module or root module has one app-level component or root component. This app-level component or root component is loaded when the app-level modules are loaded by Angular. Apart from the app-level component, this module also has reference to all external modules imported using the imports array. The module also has reference to all the services that needsto be loaded as singletons and will be available across the app.
The bootstrap property or key of the NgModule decorator specifies which component should be loaded by Angular when the app-level module loads. Angular reads the bootstrap metadata and loads the app-level component, called AppComponent.
Load App-Level Component
The TypeScript class of the app-level component, called AppComponent, is decorated with the @Component class decorator. The @Component class decorator provides the metadata about the class to Angular. It has the following three properties:
- selector
- templateURL
- styleUrls
If you are injecting a service into this component, then you will have a fourth property, as well, that references the service that will be injected into this class's constructor. The fourth property is called providers. It is an array of service classes that will be injected into this component.
Process Template
The templateURL property points to the HTML template file, which will be rendered to the browser when this component is processed. The selector property specifies the CSS selector, where the template will be inserted into the HTML.
Once platformBrowserDynamic is done with all preparation, it is ready to instantiate the app-level component or root component. platformBrowserDynamic then just iterates through the bootstrap components array and asks ApplicationRef to actually bootstrap each component.
Conclusion
Congratulations! You have learned about the internals of Angular's bootstrap process. For more information, please refer to bootstrapping in Angular.