← Back to Articles         
What Was AppModule, and What Replaced It?

What Was AppModule, and What Replaced It?

Published on 02 Oct 2026     7 min read Angular
Older Angular vs Modern Angular

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

  • AppModule was 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.ts commonly 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 AppRoutingModule class

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, AppModule was the root NgModule and AppRoutingModule commonly configured routing using RouterModule.forRoot(). In modern standalone Angular, the application is started with bootstrapApplication(), application-level providers are commonly placed in app.config.ts, and routing is typically defined in app.routes.ts and registered with provideRouter().

← Back to Articles