Understanding the Angular Boot Process

This article walks through the sequence of events that take place when an Angular application starts running. It’s aimed at newcomers, so we’ll keep things at a high level rather than digging into every internal detail.

Step-by-Step Overview

Several actions need to occur in the Web browser before an Angular app can become interactive:

  • The entry point HTML file must be fetched and parsed
  • The application’s JavaScript bundles need to be downloaded
  • The main application bundle must be run
  • That bundle is responsible for loading Angular and kicking off the bootstrap of the root module
  • Angular then initializes that root module and renders the UI

Let’s go through each stage in more detail.

The HTML Entry Point

To begin with, the browser downloads and processes the index.html file:

At its core, that HTML document must include the root component—the entry point component—which in this case is <app-root></app-root>. Once Angular has been loaded and executed, it detects that element and replaces it with the rendered template output.

That’s where everything ends up, but there’s a fair amount of work that happens beforehand. Let’s rewind and trace the path from the start.

Loading the JavaScript Bundles

If you look at the source of index.html in a freshly generated Angular project, you won’t see any script tags. That’s because the build process adds them. The Angular CLI begins by reading the angular.json (or angular-cli.json) file to understand the project setup. From that configuration, it builds the entire app.

The Angular CLI relies on Webpack under the hood, which is a module bundler. Webpack, aided by various plugins, takes the project’s source files and assets and produces JavaScript bundles. These bundles include both the application’s own code and any third-party libraries, including Angular itself.

Running ng build --prod results in several files inside the dist/<application_name> folder:

├── 3rdpartylicenses.txt
├── favicon.ico
├── index.html
├── main.1feaffbe857aaf7ee0db.js
├── polyfills.a4021de53358bb0fec14.js
├── runtime.e227d1a0e31cbccbf8ec.js
└── styles.09e2c710755c8867a460.css
Enter fullscreen mode Exit fullscreen mode

The random-looking strings after each bundle name are hashes added for cache busting. Their purpose is to make sure the Web browser fetches fresh content rather than a stale version from its local cache. Under normal circumstances, if the underlying code hasn’t changed, those hashes stay the same across multiple builds.

We’ve already covered the index.html file, so let’s examine the JavaScript files:

  • main.js: contains your application code along with everything you’ve imported
  • vendor.js: holds third-party libraries that your app depends on
  • polyfills.js: provides polyfills to support modern features in older environments, such as running Angular on legacy browsers
  • runtime.js: Webpack’s runtime utility code used for loading modules at runtime

Webpack generates these bundles and inserts them as <script> tags into index.html, as shown earlier.

It’s worth noting that additional bundles may appear if you take advantage of lazy-loaded Angular modules.

Because these script tags live inside index.html, the browser downloads them as well. However, downloading isn’t enough—the code still needs to run before the app can start. We’ll explore that next.

Executing the Main Entry Point

The main bundle is what matters here. As mentioned earlier, it holds all of the application’s code.

But with the entire app bundled in one file, which part gets executed first? That’s determined by settings in angular.json:

The main property, shown on line 19 of the snippet above, specifies which module should be loaded and executed as soon as the main JavaScript bundle is available at runtime.

By default, that module is main.ts. Thanks to this configuration, the Angular CLI arranges for Webpack to load and run that module right after all bundles have been fetched.

Now you know that main.ts serves as the app’s entry point—and why it gets loaded and executed. Let’s look at what actually happens inside that file!

Bootstrapping the Angular Application

Assuming you haven’t modified anything, main.ts looks like this:

There’s quite a bit going on here.

First, you’ll see a set of import statements. These remain in place after the compiler transpiles the code to JavaScript. At runtime, Webpack handles those imports, and once they’ve been processed, the remaining code starts executing.

Second, if the project was built for production, Angular’s production mode gets enabled. This is crucial for performance.

Finally—and most importantly—this line runs:

platformBrowserDynamic().bootstrapModule(AppModule);
Enter fullscreen mode Exit fullscreen mode

It’s just one line, but it accomplishes a great deal. The platformBrowserDynamic part is responsible for loading Angular within a browser environment. It pulls in the framework pieces that are needed and handles the necessary setup. Since Angular can also run in other contexts—mobile, server-side, and so on—there are different ways to load it beyond this one.

So the first segment, platformBrowserDynamic(), loads Angular. Once that completes, the second part, bootstrapModule(...), tells Angular to bootstrap whatever module is passed in. In standard Angular projects, that’s at least an AppModule.

From there, Angular takes charge. It loads all the components, services, directives, pipes, and anything else the AppModule imports, references, or declares. Eventually, it looks for a component that matches the app-root selector. In most projects, that component is the AppComponent:

Once Angular locates that component, it renders it and updates the page’s DOM with the resulting content.

If you’d like to explore further, these resources might help:

Wrapping Up

This overview covered the main steps behind Angular application startup. There’s plenty more nuance involved—this was intentionally kept at a high level—but hopefully it gives you a solid mental model of how the pieces fit together.

That’s all for now!