Skip to main content

On This Page

Angular Modules Still Vital in Angular 21 — Key Differences Between NgModules and Standalone Components

3 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

NgModule

Angular Modules (NgModules) continue to be fully supported across all active versions through Angular 21 despite the introduction of standalone components back in v14. The old bootstrap function platformBrowserDynamic was deprecated; developers must now exclusively use platformBrowser().bootstrapModule() instead.

Why This Matters

While new projects rightfully favour simpler standalone components without explicit module files, countless enterprise applications still rely on NgModules for logical grouping, shared services via providers arrays, and fine-grained control over what gets exported.

The transition period creates friction when teams mix both approaches incorrectly—the single most common mistake is misplacing components between declarations and imports, leading to baffling compiler errors that slow down development.

Key Insights

  • ‘declarations’ only accepts non‑standalone (standalone : false) components — putting a modern v17+ default standalone here triggers an immediate compile-time error.
  • ‘imports’ expects either other NgModules or standalone directives/components/pipes — never place non‑standalone items here.
  • ‘CommonModule’ replaces ‘BrowserModule’ inside any feature/lazy-loaded module — importing BrowserMore than once crashes your entire application at runtime.
  • For lazy-loading legacy modules you still use loadChildren returning an imported class; modern standalones leverage loadComponent directly without any intermediate file.
  • The bootstrap mechanism changed officially starting from version 21 where @angular/platform-browser-dynamic was removed entirely — switch every project now uses @angular/platform-browser’s synchronous API.

Working Examples

Typical root module skeleton showing how declarations hold non‑standalone root component while imports mix other NgModuls plus any needed pipes/directives.

@NgModule({
    declarations: [App],
    bootstrap   : [App],
    imports     : [BrowserModule , CommonModul , Tasks , NewTask , Task , User , Header , RouterOutlet]
})
export class AppModul {}

Demonstrates why mixing up ‘declaratios’ versus ‘imorts’ produces compilation failures after V17 introduced default standalon flag.

// ❌ wrong placement
@Component({ selector:'bad-example' })
export class BadComp{} // defaults to standalon true => cannot go into declaratios

// ✅ correct usage
@NgModule({
    declaratios:[NonStandAloneComp],
    importts:[StandAloneHeader]
})
export class WorkingModul{}

Lazy loading configuration distinguishing global .forRoot call from repeated .forChild inside each lazily-loaded submodule.

export const routes : Routes = [{
 path:'tasks',
 loadChildren : () => import('./tasks/tasks.modul').then(m => m.TasksModul)
}];

@NgModule({
 ...
 importst:[RouterModul.forRoot(routes)] // root level
})
export class RootRouteConfig {}

// inside feature modul:
named('task-routing')[
something]...
typical pattern where .forRoot reserved once globally ; .forChild used everywhere else .

Practical Applications

  • A large dashboard app organises dozens of screens into dedicated feature moduls—each exports only its public container(s); forgetting an export forces consuming moduls either copy-paste workaround or broken templates.
  • ‘Pitfall’ : Accidentally referencing ‘BrowsrModul’ inside e.g., AdminFeatures.Module silently fails because second registration duplicates provider registrations causing cryptic startup crash.
  • ‘Workflow’ : Migrating older monolith piecemeal by wrapping each screen set inside its own Moduls while keeping rest unchanged avoids rewriting everything overnight yet respects new standards wherever possible.
  • ‘Anti-pattern’ : Placing every reusable pipe/directive directly into ‘exports’ without first declaring them yields silent compilation warnings often overlooked until production build breaks tree-shaking logic.

References:

Continue reading

Next article

Angular Tutorials: A Structured Reference for Modern Angular Devs

Related Content