How Is Angular Bootstrapped Now?
In modern Angular using standalone APIs, an Angular application is typically bootstrapped using the bootstrapApplication() function.
This replaces the traditional approach of bootstrapping a root NgModule such as AppModule.
1. What Is Bootstrapping in Angular?
Bootstrapping means starting the Angular application.
When the browser loads the application, Angular needs to know:
- Which component is the root component
- Which application-wide services/providers are required
- Which router configuration should be used
- Which HTTP configuration should be used
- Where the root component should be rendered in the HTML
Modern Angular commonly starts with:
bootstrapApplication(App, appConfig);
Here:
App
↓
Root Component
appConfig
↓
Application-wide configuration/providers
2. Modern Standalone Angular Structure
A simple application may look like:
src/
│
├── main.ts
│
├── index.html
│
└── app/
├── app.ts
├── app.html
├── app.config.ts
└── app.routes.ts
The important file that actually starts Angular is:
main.ts
3. Full Simple Sample Program
Suppose we have two pages:
Home
Products
We'll configure:
- Standalone components
- Routing
HttpClient- Application bootstrap
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AngularApp</title>
<base href="/">
</head>
<body>
<app-root></app-root>
</body>
</html>
The important part is:
<app-root></app-root>
Angular will locate this element and render the root component there.
4. Root Component — app.ts
import { Component } from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
imports: [
RouterLink,
RouterOutlet
],
templateUrl: './app.html'
})
export class App {
title = 'My Angular Application';
}
Notice that there is no:
@NgModule
The component directly declares what it needs through:
imports: [
RouterLink,
RouterOutlet
]
In modern Angular, components are standalone by default.
5. Root Template — app.html
<h1>{{ title }}</h1>
<nav>
<a routerLink="/">Home</a>
|
<a routerLink="/products">Products</a>
</nav>
<hr>
<router-outlet></router-outlet>
The routed component will be displayed inside:
<router-outlet></router-outlet>
6. Home Component — home.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
template: `
<h2>Home</h2>
<p>Welcome to the Angular application.</p>
`
})
export class Home {
}
7. Products Component — products.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-products',
template: `
<h2>Products</h2>
<p>Product page loaded successfully.</p>
`
})
export class Products {
}
8. Configure Routes — app.routes.ts
import { Routes } from '@angular/router';
import { Home } from './home';
import { Products } from './products';
export const routes: Routes = [
{
path: '',
component: Home
},
{
path: 'products',
component: Products
}
];
The routes define:
URL Component
---------------------------
/ Home
/products Products
9. Application Configuration — app.config.ts
Application-level providers are normally configured here.
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
Here we configure two important Angular services.
Router
provideRouter(routes)
Registers Angular Router.
HttpClient
provideHttpClient()
Registers HttpClient, allowing services/components to call APIs such as an ASP.NET Core Web API.
For example:
this.http.get('https://localhost:7001/api/products');
10. Bootstrap Angular — main.ts
This is the most important part.
import { bootstrapApplication } from '@angular/platform-browser';
import { App } from './app/app';
import { appConfig } from './app/app.config';
bootstrapApplication(App, appConfig)
.catch(err => console.error(err));
This starts the Angular application.
The key statement is:
bootstrapApplication(App, appConfig);
11. Detailed Bootstrap Flow
When the browser opens the application, the process is roughly:
Browser
↓
index.html
↓
main.ts
↓
bootstrapApplication()
↓
Root Component: App
↓
Application Configuration: appConfig
↓
Providers registered
├── Router
└── HttpClient
↓
Angular finds
<app-root>
↓
App component rendered
↓
Router starts
↓
Home / Products components rendered
Let's examine this more closely.
Step 1 — Browser Loads index.html
The browser initially contains:
<app-root></app-root>
At this point, <app-root> is simply an HTML element.
Angular hasn't rendered the application yet.
Step 2 — Angular Executes main.ts
Angular reaches:
bootstrapApplication(App, appConfig);
This tells Angular:
Start the application using
Appas the root component andappConfigas the application configuration.
Step 3 — Angular Reads the Root Component
Angular examines:
@Component({
selector: 'app-root'
})
export class App {
}
The selector is:
app-root
Step 4 — Angular Finds the Selector
Angular searches index.html for:
<app-root></app-root>
It finds the matching element.
Step 5 — Angular Creates the Root Component
Angular creates:
App
and renders:
<h1>{{ title }}</h1>
inside:
<app-root>
Conceptually:
<body>
<app-root>
<h1>My Angular Application</h1>
...
</app-root>
</body>
Step 6 — Angular Registers Global Providers
Angular reads:
appConfig
which contains:
providers: [
provideRouter(routes),
provideHttpClient()
]
Therefore services such as:
Router
HttpClient
become available through Angular dependency injection.
12. Why Do We Have app.config.ts?
Before standalone APIs, global configuration was commonly placed inside:
AppModule
For example:
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule
]
})
export class AppModule {
}
With standalone APIs, much of this configuration moves to:
app.config.ts
For example:
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
So you can think of it as:
Old Angular
AppModule
↓
Global Angular configuration
Modern Standalone Angular
app.config.ts
↓
Application-level providers/configuration
They are not technically identical concepts, but app.config.ts takes over many of the configuration responsibilities that were previously handled through the root NgModule.
13. Old Angular vs Modern Angular
Traditional NgModule approach
The old main.ts commonly looked like:
import { platformBrowserDynamic }
from '@angular/platform-browser-dynamic';
import { AppModule }
from './app/app.module';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
Flow:
main.ts
↓
bootstrapModule(AppModule)
↓
AppModule
↓
bootstrap: [AppComponent]
↓
AppComponent
Modern standalone approach
Now:
import { bootstrapApplication }
from '@angular/platform-browser';
import { App }
from './app/app';
import { appConfig }
from './app/app.config';
bootstrapApplication(App, appConfig)
.catch(err => console.error(err));
Flow:
main.ts
↓
bootstrapApplication()
↓
App
↓
Application starts
There is no requirement for:
AppModule
14. Side-by-Side Comparison
| Traditional Angular | Modern Standalone Angular |
|---|---|
AppModule |
Root standalone component |
bootstrapModule() |
bootstrapApplication() |
NgModule |
Standalone APIs |
AppRoutingModule |
app.routes.ts |
HttpClientModule |
provideHttpClient() |
| RouterModule configuration | provideRouter() |
| Module-centric | Component/provider-centric |
15. Can We Put Everything Directly in main.ts?
Yes.
For a very small application, you could write:
import { bootstrapApplication }
from '@angular/platform-browser';
import { provideRouter }
from '@angular/router';
import { provideHttpClient }
from '@angular/common/http';
import { App }
from './app/app';
import { routes }
from './app/app.routes';
bootstrapApplication(App, {
providers: [
provideRouter(routes),
provideHttpClient()
]
})
.catch(err => console.error(err));
This works.
But separating configuration into:
app.config.ts
keeps main.ts clean.
Then:
bootstrapApplication(App, appConfig);
is easier to maintain.
16. Angular + ASP.NET Core Example
In your Angular + ASP.NET Core architecture, the startup flow would look like:
Browser
↓
Angular index.html
↓
main.ts
↓
bootstrapApplication(App, appConfig)
↓
Angular Application
↓
Router / HttpClient / Interceptors
↓
Angular Service
↓
HTTP Request
↓
ASP.NET Core Web API
↓
Application Layer
↓
Infrastructure
↓
SQL Server
Angular itself is bootstrapped independently of ASP.NET Core.
ASP.NET Core does not bootstrap Angular.
Even if ASP.NET Core hosts the Angular static files, the Angular application still starts in the browser using:
bootstrapApplication()
Key Points
- Bootstrapping means starting the Angular application.
- Modern standalone Angular uses:
bootstrapApplication()
- It is imported from:
@angular/platform-browser
- The typical startup statement is:
bootstrapApplication(App, appConfig);
Appis the root component.appConfigcontains application-wide providers/configuration.- Routing is commonly registered using:
provideRouter(routes)
HttpClientis commonly registered using:
provideHttpClient()
- Modern standalone Angular does not require
AppModule. - Older Angular applications commonly used:
platformBrowserDynamic()
.bootstrapModule(AppModule);
- Modern Angular commonly uses:
bootstrapApplication(App, appConfig);
Easy way to remember
OLD
main.ts
↓
AppModule
↓
AppComponent
MODERN
main.ts
↓
bootstrapApplication()
↓
App
Interview Questions and Answers
1. How is Angular bootstrapped in modern standalone applications?
Modern Angular applications are typically bootstrapped using:
bootstrapApplication(App, appConfig);
It directly bootstraps the root standalone component without requiring an AppModule.
2. What is bootstrapApplication()?
bootstrapApplication() is the standalone API used to start an Angular application using a root component.
bootstrapApplication(App);
3. Where is bootstrapApplication() normally called?
Usually in:
src/main.ts
Example:
bootstrapApplication(App, appConfig);
4. What is the purpose of app.config.ts?
It commonly contains application-wide providers and configuration.
For example:
providers: [
provideRouter(routes),
provideHttpClient()
]
5. Is AppModule required in modern standalone Angular?
No. A standalone application can directly bootstrap its root component:
bootstrapApplication(App);
6. How was Angular bootstrapped before standalone APIs?
Traditionally:
platformBrowserDynamic()
.bootstrapModule(AppModule);
The AppModule then identified the root component.
7. What is the difference between bootstrapModule() and bootstrapApplication()?
bootstrapModule()
↓
Bootstraps an NgModule
bootstrapApplication()
↓
Bootstraps a standalone root component
8. Where are global providers configured in standalone Angular?
They can be provided to bootstrapApplication(), commonly through:
appConfig
Example:
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
9. What is the root component?
It is the top-level Angular component used to start the component tree.
For example:
@Component({
selector: 'app-root'
})
export class App {
}
and:
bootstrapApplication(App);
10. What happens when an Angular application starts?
A concise interview answer is:
The browser loads
index.html, the Angular bundle executesmain.ts, andbootstrapApplication()creates the application using the root component. Angular initializes dependency injection and configured providers, finds the root component's selector such as<app-root>, and renders the Angular component tree into the page.
Interview one-line answer
Modern Angular is bootstrapped from
main.tsusingbootstrapApplication(), which starts the application with a standalone root component and application-level providers, eliminating the need for a rootAppModule.