Angular Bootstrapping : How does Angular work under the hood?

yeshasmp

Yeshas M P

Posted on January 17, 2022

Angular Bootstrapping : How does Angular work under the hood?

In this article we are going to explore together how Angular apps work behind the scenes. At first, we will understand various workspace and application configuration files and finally we will piece together all the files how they are involved in bootstraping.

Angular Project Structure

Before understanding how Angular works under the hood, it’s necessary to understand the workspace structure and application configuration involved in the process. Every Angular apps works in the context of workspace. By default ng new app_name command generates a skeleton application at root of workspace in below fashion -

workspace/(folder name is app_name given at cmd)
  ... (workspace-wide config files)
    src/ --(source and support files for application)

Enter fullscreen mode Exit fullscreen mode

The above structure is usually referred as ‘multi-repo’ development style where each application has it’s own workspace, ‘workspace’ folder consists of workspace specific configuration files where as ‘src’ folder consists of application specific files and folders.

Workspace configuration files

  • angular.json - It specifies workspace-wide and project specific defaults for build and development. For instance, You can have ‘n’ number of npm packages installed in your workspace, but you can specify which packages you want in your application in angular.json
  • package.json - It consists metadata of project and is used for managing the project’s dependencies, scripts, npm package versions and many more.
  • package-lock.json - It provides information of all npm packages installed in npm_modules folder such as package version, hash to verify the package integrity and list of its dependencies.
  • tsconfig.json - Since Angular apps are written using typescript, this file specifies root files and compiler options required to compile our application.

Application configuration files

  • index.html - This is our main HTML page which is rendered and is displayed to user in browser.
  • main.ts - This is responsible for compiling all components and template files with JIT(Just In Time) compiler. We can also use AOT(Ahead Of Time) compiler by adding –aot flag to ng build or ng serve CLI commands(Recommended for production environment).

For more detailed explanation of all config files go through official Angular Docs

Angular Bootstrapping

Some of you all might have wondered when I used the term ‘Bootstraping’ earlier. In Angular eco-system Bootstraping is technique of initializing root module and loading root component into index.html file. When we run ng serve or ng build multiple things happen in the background. Below steps provide a brief overview of bootstrapping process-

Angular Bootstrapping

  • Compilation of application codes using tsc typescript compiler.
  • Bundling and minification of javascript files by Webpack.
  • Deployment and bootstrapping.
  • Run JIT compiler for all components, directives and pipes.
  • Render index.html in browser.

The only difference between JIT and AOT compiler is that in AOT compiler, compilation takes place during build time rather than at runtime in browser. Let’s go through above steps in bit more detail -

1) angular.json consist of multiple configuration properties related build and development. The one’s which are interesting to us are ‘builder’, ‘index’ and ‘main’ properties under ‘build’ as shown below.

"build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            .......
            "index": "src/index.html",
            "main": "src/main.ts",
            .......
          }

Enter fullscreen mode Exit fullscreen mode

When we run ng serve or ng build Angular CLI looks at angular.json for these properties. ‘builder’ property is saying to Angular CLI where it can find Architect builders to build Angular apps for browser environment. where as our ‘index’ and ‘main’ properties specifies index.html file to be rendered in browser and main.ts which handles bootstrapping process. Then Angular CLI calls tsc typescript compiler to transpile all the typescript codes into javascript codes using configuration provided in tsconfig.json.

2) If we look at index.html file of newly generated Angular app, it only has <app-root> element inside <body> tag. <app-root> is root component template which is injected at runtime. Apart from these there is neither any javascript file or any reference to style links.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>SampleApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="styles.a7a7ed6d783a0950.css" media="print" onload="this.media='all'">
  <noscript>
    <link rel="stylesheet" href="styles.a7a7ed6d783a0950.css">
  </noscript>
</head>
<body>
  <app-root></app-root>
  <script src="runtime.0298365924d274ea.js" type="module"></script>
  <script src="polyfills.daf14d28d6c3636f.js" type="module"></script>
  <script src="main.94e04dd2c597738f.js" type="module"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

After transpiling all the typescript codes, Angular CLI then uses Webpack, a module bundler to minify and bundle all the files which are then added as reference into index.html file. Let’s look at each of these files :

  • runtime.js - It contains utility codes used by Webpack to load other files.
  • vendor.js - It contains 3rd party library codes which are imported in our ngModules.
  • polyfill.js - It contains polyfills required to make our app compatible among different browsers.
  • main.js - It contains all the javascript codes written in our application.

When we run ng serve application codes are built at local environment and served from memory, where as ng build outputs all the transpiled codes into dist folder from where it can be deployed to any hosting vendor and served from there.

3) At runtime in browser, main.js is responsible for bootstraping our Angular apps. It contains all our application codes and how to compile and run it. We earlier learnt Angular CLI looks at angular.json to find main.ts file. If we look at main.ts file it consist couple of import statements along with some lines of code.

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));

Enter fullscreen mode Exit fullscreen mode

Apart from import statements, we are having code to enable production mode if target environment is production but the line which is interesting to us is platformBrowserDynamic().bootstrapModule(AppModule);. Though it’s single line, lot of action takes place when executed by Angular CLI.

  • At first, We are importing platformBrowserDynamic module from @angular/platform-browser-dynamic library.
  • Then we are calling platformBrowserDynamic().bootstrapModule(AppModule) by passing our root AppModule as parameter.
  • Internally bootstrapModule creates an instance of compiler JIT compiler, where it crawls through all components, directives and pipes declared in AppModule @NgModule decorator and other feature modules imported in AppModule.
  • Once it finds Component having ‘app-root’ as its selector, it will render the component template in index.html.

But how does Angular know where to find template for <app-root> in index.html? Let’s find out in next section.

4) From the root AppModule we passed earlier, it refers @ngModule decorator in AppModule. @NgModule decorator contains metadata of all the components, directives and pipes under it along with other feature modules imported under AppModule. It also specifies services which are available at app-level under providers and bootstrap property specifying the root component as shown below.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Enter fullscreen mode Exit fullscreen mode

5) Once it finds the root AppComponent, it then refers @Component decorator in AppComponent. @Component contains metadata of below properties :

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'SampleApp';
}

Enter fullscreen mode Exit fullscreen mode

There it is! app-root specified in selector matches with app-root in index.html. It then finds HTML template along with styles and renders the same in index.html where app-root is present.

Conclusion

Though above explanation is not complete, I hope it gave you brief idea on what’s happening under the hood when we run Angular app. Stay tuned for more such interesting articles!

💖 💪 🙅 🚩
yeshasmp
Yeshas M P

Posted on January 17, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related