Angular Standalone Routing Explained — How provideRouter() Works Without AppModule
With Angular 15 and later, the framework introduced a standalone component architecture — making Angular applications cleaner and more modular by removing the need for NgModule.
If you're wondering where AppModule and RouterModule.forRoot() disappeared, you're not alone! In this guide, you’ll learn:
- How routing works in modern Angular
- How to configure routes with
provideRouter() - How Angular internally handles navigation
- A complete working example with standalone components
Step 1: Your Project Setup
In new Angular projects (created via )ng new my-app --standalone you’ll typically see these two files:
app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(),
]
};
app.routes.ts
import { Routes } from '@angular/router';
export const routes: Routes = [];
No AppModule needed — the configuration lives in app.config.ts and app.routes.ts.
Step 2: Define Routes
Define routes normally, but now use standalone components:
// app.routes.ts
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
export const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: '**', redirectTo: '' }
];
Step 3: Create Standalone Components
home.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
standalone: true,
template: `Welcome Home!
`,
})
export class HomeComponent {}
about.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-about',
standalone: true,
template: `About Us
`,
})
export class AboutComponent {}
Step 4: Bootstrap the Application
Angular now bootstraps your app using bootstrapApplication() instead of AppModule:
main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch(err => console.error(err));
app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
template: `
My Angular App
`,
})
export class AppComponent {}
Step 5: How provideRouter() Works Internally
Under the hood, provideRouter(routes) replaces RouterModule.forRoot(routes). It registers all routing-related providers into Angular’s dependency injection (DI) system:
Routerservice for navigationRouterOutletdirective for rendering componentsRouterLinkdirective for link handling
The flow looks like this:
bootstrapApplication()creates the root injectorprovideRouter(routes)adds router providers- The Router parses the URL and renders the matching component inside
<router-outlet>
Step 6: Why No AppModule?
| Old Angular | New Standalone |
|---|---|
AppModule with RouterModule.forRoot() | app.config.ts with provideRouter(routes) |
bootstrapModule(AppModule) | bootstrapApplication(AppComponent, appConfig) |
| NgModule imports & declarations | Component-level imports via standalone: true |
This new approach makes Angular apps faster, simpler, and more tree-shakable.
Folder Structure
src/
├─ app/
│ ├─ app.component.ts
│ ├─ app.config.ts
│ ├─ app.routes.ts
│ ├─ home/
│ │ └─ home.component.ts
│ └─ about/
│ └─ about.component.ts
└─ main.ts
Conclusion
Angular’s new standalone routing system with provideRouter() is the future of Angular development.
It removes the need for modules, simplifies setup, and improves app performance.
Now you can define routes directly, use standalone components, and enjoy a cleaner Angular architecture.
No comments:
Post a Comment