Going Standalone: Modernizing Angular Without NgModules
Standalone components changed how I structure Angular apps. A field guide to migrating incrementally without freezing feature work.
At Mofid I inherited a large Angular application built the classic way: a forest of NgModules, a shared module that imported everything, and a dependency graph nobody fully understood. Standalone components offered a way out — but you cannot stop the world to rewrite an app in production. Here is how we migrated incrementally.
What standalone actually removes
An NgModule did three jobs: it declared components, it imported dependencies, and it provided services. Standalone components fold the first two into the component itself. Instead of declaring a component in a module and importing that module elsewhere, the component states its own dependencies:
import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink } from "@angular/router";
@Component({
selector: "app-user-card",
standalone: true,
imports: [CommonModule, RouterLink],
template: `
<a [routerLink]="['/users', user.id]">{{ user.name }}</a>
`,
})
export class UserCardComponent {
@Input({ required: true }) user!: User;
}The dependency list lives next to the thing that uses it. No more hunting through a shared module to figure out why a pipe is or is not available.
Bootstrap without a root module
The migration starts at the entry point. Replace platformBrowserDynamic().bootstrapModule(AppModule) with bootstrapApplication, and move your providers into the application config:
import { bootstrapApplication } from "@angular/platform-browser";
import { provideRouter } from "@angular/router";
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { AppComponent } from "./app/app.component";
import { routes } from "./app/app.routes";
import { authInterceptor } from "./app/auth.interceptor";
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor])),
],
});Migrate leaves first
The safe order is bottom-up. Start with presentational components that have no children to worry about, flip them to standalone: true, and remove them from their NgModule's declarations. The Angular schematic automates a lot of this:
ng generate @angular/core:standaloneIt runs in stages — convert components, prune now-empty modules, then switch bootstrap. Run one stage, commit, ship. We did this over several sprints without ever blocking feature work, because standalone and NgModule-based code interoperate cleanly. A standalone component can be imported into an old NgModule, and an NgModule's exports can be imported into a standalone component via its imports array.
Lazy routes get dramatically simpler
This was the payoff our team felt most. Lazy loading no longer needs a feature module — you point a route at a component or a route file directly:
import { Routes } from "@angular/router";
export const routes: Routes = [
{
path: "reports",
loadComponent: () =>
import("./reports/reports.component").then((m) => m.ReportsComponent),
},
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.adminRoutes),
},
];What I would tell my past self
- Do not big-bang it. Incremental migration is fully supported and far less risky.
- Delete the god
SharedModulelast, and replace it with a barrel file of standalone imports rather than another module. - Adopt the new
inject()function while you are in there — it pairs naturally with standalone and cleans up constructor injection. - Lean on the schematic, but review every diff. It is good, not infallible, especially around providers.
Standalone did not just remove boilerplate — it made the dependency graph legible. New engineers could finally read a component and know exactly what it needed.
Angular gets unfairly maligned for ceremony, and NgModules were a big part of that reputation. Standalone components are the framework shedding weight it no longer needs — and an app that migrates to them is genuinely easier to reason about.