1. What Was AppModule, and What Replaced It?
What was AppModule?
Before Angular's standalone APIs, Angular applications were primarily organized around NgModules.
AppModule was the root NgModule of the application.
It was normally defined in:
src/app/app.module.ts
A typical AppModule looked like this:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule
],
providers: [],
bootstrap: [
AppComponent
]
})
export class AppModule {
}
AppModule had several important responsibilities:
| Section | Purpose |
|---|---|
declarations |
Declared components, directives and pipes |
imports |
Imported other Angular modules |
providers |
Registered services/providers |
bootstrap |
Specified the root component |
How Was AppModule Started?
The old main.ts contained:
import { platformBrowserDynamic }
from '@angular/platform-browser-dynamic';
import { AppModule }
from './app/app.module';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
The startup flow was:
main.ts
↓
bootstrapModule(AppModule)
↓
AppModule
↓
@NgModule
↓
bootstrap: [AppComponent]
↓
AppComponent
↓
<app-root>
So Angular first bootstrapped the module, and the module told Angular which component to bootstrap.
What Replaced AppModule?
There isn't one single file that is a perfect one-for-one replacement.
With standalone Angular, the responsibilities previously concentrated in AppModule are distributed among:
main.ts
+
Root standalone component
+
app.config.ts
Most importantly, instead of:
bootstrapModule(AppModule)
we now use:
bootstrapApplication(App, appConfig)
Modern Standalone Example
main.ts
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));
Now Angular directly starts:
App
instead of first starting:
AppModule
app.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
imports: [
RouterOutlet
],
template: `
<h1>My Angular Application</h1>
<router-outlet></router-outlet>
`
})
export class App {
}
The component directly imports what its template needs:
imports: [
RouterOutlet
]
Previously, many dependencies were imported through an NgModule.
app.config.ts
Application-level providers are commonly placed 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()
]
};
For example, instead of the old:
imports: [
HttpClientModule
]
modern standalone applications commonly use:
providers: [
provideHttpClient()
]
Old vs New AppModule
Before Standalone
main.ts
↓
AppModule
↓
@NgModule
├── declarations
├── imports
├── providers
└── bootstrap
↓
AppComponent
Modern Standalone
main.ts
↓
bootstrapApplication()
↓
App
+
appConfig
↓
Application starts
So an easy way to remember is:
OLD
AppModule
↓
Central NgModule configuration
MODERN
App standalone component
+
app.config.ts
+
bootstrapApplication()
Key Points — AppModule
AppModulewas the application's root NgModule.- It used the
@NgModule()decorator. - It declared components/directives/pipes and imported other NgModules.
- It specified the root component through:
bootstrap: [AppComponent]
- Old Angular bootstrapped it using:
bootstrapModule(AppModule)
- Modern standalone Angular does not require a root
AppModule. - Modern Angular directly bootstraps the root component:
bootstrapApplication(App, appConfig);
app.config.tscommonly holds application-wide providers.
2. What Was AppRoutingModule, and What Replaced It?
What was AppRoutingModule?
AppRoutingModule was a conventional NgModule used to configure application routing.
It was commonly located at:
src/app/app-routing.module.ts
Example:
import { NgModule } from '@angular/core';
import {
RouterModule,
Routes
} from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ProductsComponent } from './products/products.component';
const routes: Routes = [
{
path: '',
component: HomeComponent
},
{
path: 'products',
component: ProductsComponent
}
];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
}
Its main job was:
RouterModule.forRoot(routes)
This configured the Angular Router with the application's root routes.
How Was It Connected to AppModule?
AppRoutingModule was imported by AppModule:
@NgModule({
imports: [
BrowserModule,
AppRoutingModule
]
})
export class AppModule {
}
The architecture looked like:
main.ts
↓
AppModule
↓
AppRoutingModule
↓
RouterModule.forRoot(routes)
↓
Angular Router
What Replaced AppRoutingModule?
In a modern standalone Angular application, routing is commonly split into:
app.routes.ts
+
provideRouter(routes)
The routes themselves go into:
app.routes.ts
and the router is registered through:
provideRouter(routes)
usually in:
app.config.ts
Modern Routing Example
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
}
];
Notice there is:
- No
@NgModule - No
RouterModule.forRoot() - No
AppRoutingModuleclass
It is simply a route configuration.
app.config.ts
Now register those routes:
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes)
]
};
The important line is:
provideRouter(routes)
This configures Angular Router for the application.
app.ts
The root component can import RouterOutlet directly:
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
imports: [
RouterOutlet
],
template: `
<h1>Angular Application</h1>
<router-outlet></router-outlet>
`
})
export class App {
}
Complete Modern Routing Flow
main.ts
↓
bootstrapApplication(App, appConfig)
↓
app.config.ts
↓
provideRouter(routes)
↓
app.routes.ts
↓
Angular Router configured
↓
RouterOutlet
↓
Routed Component
For example:
/products
↓
Angular Router
↓
routes
↓
{
path: 'products',
component: Products
}
↓
Products component
↓
<router-outlet>
Old vs New Routing
Old
app-routing.module.ts
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
Then:
AppModule
↓
imports AppRoutingModule
Modern
app.routes.ts
contains:
export const routes: Routes = [
{
path: '',
component: Home
}
];
Then:
app.config.ts
contains:
provideRouter(routes)
No routing NgModule is required.
RouterModule.forRoot() vs provideRouter()
Old
RouterModule.forRoot(routes)
Modern standalone
provideRouter(routes)
Conceptually:
OLD
routes
↓
RouterModule.forRoot(routes)
↓
AppRoutingModule
↓
AppModule
MODERN
routes
↓
provideRouter(routes)
↓
appConfig
↓
bootstrapApplication()
Final Comparison
| Before Standalone APIs | Modern Standalone Angular |
|---|---|
AppModule |
No root NgModule required |
@NgModule() |
Standalone components + provider APIs |
bootstrapModule(AppModule) |
bootstrapApplication(App, appConfig) |
declarations |
Component-level imports |
NgModule providers |
Application/component providers |
AppRoutingModule |
app.routes.ts + provideRouter() |
RouterModule.forRoot(routes) |
provideRouter(routes) |
HttpClientModule |
provideHttpClient() |
The easiest interview memory trick is:
BEFORE
main.ts
↓
AppModule
↓
AppRoutingModule
↓
AppComponent
NOW
main.ts
↓
bootstrapApplication()
↓
App + appConfig
↓
provideRouter()
↓
app.routes.ts
Interview Questions and Answers
1. What was AppModule?
AppModule was the root NgModule of a traditional Angular application. It declared components, imported modules, registered providers, and identified the root component.
2. What replaced AppModule?
There is no exact single replacement. In standalone Angular, its responsibilities are distributed across the root standalone component, app.config.ts, and bootstrapApplication().
bootstrapApplication(App, appConfig);
3. Is app.config.ts the exact replacement for AppModule?
No. app.config.ts handles much of the application-level provider configuration, but standalone components handle their own template dependencies, while bootstrapApplication() handles application startup.
This distinction is important in interviews.
4. What was AppRoutingModule?
AppRoutingModule was a conventional NgModule used to configure application routing, commonly using:
RouterModule.forRoot(routes)
5. What replaced AppRoutingModule?
Standalone Angular commonly uses:
app.routes.ts
+
provideRouter(routes)
For example:
providers: [
provideRouter(routes)
]
6. What replaced RouterModule.forRoot(routes)?
For standalone application configuration, the common equivalent is:
provideRouter(routes)
7. Do we still need RouterModule?
Not as a root routing module just to configure standalone routing. You can register the router with:
provideRouter(routes)
and import individual router directives such as:
imports: [
RouterOutlet,
RouterLink
]
where needed.
Interview Quick Answer
Before standalone Angular,
AppModulewas the root NgModule andAppRoutingModulecommonly configured routing usingRouterModule.forRoot(). In modern standalone Angular, the application is started withbootstrapApplication(), application-level providers are commonly placed inapp.config.ts, and routing is typically defined inapp.routes.tsand registered withprovideRouter().