Angular 57: Migration Mindset — NgModules vs Standalone
easy⏱ 5 mincourseangular
The old way: NgModule + platformBrowserDynamic
This is how every Angular app bootstrapped before v14 introduced standalone components, and it's still valid Angular today. AppModule declares which components belong to it, imports BrowserModule for browser rendering, and lists AppComponent as the one to bootstrap. platformBrowserDynamic().bootstrapModule(AppModule) then boots that module from main.ts.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
bootstrap: [AppComponent],
})
export class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule).catch((err) => console.error(err));
Standalone components can import an NgModule, and vice versa
Migration doesn't require touching everything at once: a standalone component can list a legacy NgModule in its imports array to reuse its declarations, and an NgModule's declarations can still reference components while the rest of the app moves to bootstrapApplication. This is the officially supported path — convert one component, one route, one module at a time.
Same rendered result, radically less ceremony
Both versions boot an app that renders the same AppComponent. The standalone version needs no module wrapper, no declarations array, and no bootstrap array — the component and the bootstrap call say everything the module used to.