Chapter 5: Standalone vs. NgModules
When Angular was first released in 2016, NgModules were at the heart of every application. They provided a way to group components, directives, pipes, and services together. But as applications grew, many developers found the module system verbose and confusing for newcomers.
With Angular v14 (2022), the framework introduced standalone components — a simpler, more direct way to build apps without NgModules. Since then, standalone APIs have become a cornerstone of Angular’s modernization.
In this chapter, we’ll explore what standalone components are, how they compare to NgModules, and when you should use one over the other.
5.1 A Quick Refresher: What Are NgModules?
Traditionally, Angular apps required at least one root module (usually AppModule) and often many feature modules.
Example of a basic NgModule:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world/hello-world.component';
@NgModule({
declarations: [AppComponent, HelloWorldComponent],
imports: [BrowserModule, FormsModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
Here:
- declarations register components, directives, and pipes.
- imports bring in other modules (like
FormsModule). - bootstrap defines the entry component.
This pattern worked, but it also created confusion: Do I declare this in the module or import it? Where does a service go?
5.2 What Are Standalone Components?
A standalone component removes the need for NgModules. Instead of declaring a component in a module, you mark it as standalone: true.
Example:
import { Component } from '@angular/core';
@Component({
selector: 'app-hello-world',
standalone: true,
template: `<h1>Hello, Angular (Standalone)!</h1>`
})
export class HelloWorldComponent {}
Notice that we no longer need to declare this component inside AppModule. It is self-contained.
5.3 Bootstrapping a Standalone Application
Instead of bootstrapping with AppModule, we use bootstrapApplication() directly in main.ts:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent)
.catch(err => console.error(err));
This makes the entry point simpler and removes the need for a root module altogether.
5.4 Importing Dependencies
With NgModules, you imported dependencies inside the imports array of the module.
With standalone components, you import them directly in the component metadata:
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-user-form',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<input [(ngModel)]="username" placeholder="Enter your name">
<p>You typed: {{ username }}</p>
`
})
export class UserFormComponent {
username = '';
}
The imports array now lives inside the component, not a module.
5.5 Feature Composition with Standalone APIs
Standalone doesn’t mean isolated — you can still build large applications by composing features.
For example, a feature component can import another standalone component directly:
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [HelloWorldComponent],
template: `
<h2>Dashboard</h2>
<app-hello-world></app-hello-world>
`
})
export class DashboardComponent {}
This eliminates the need to juggle multiple feature.modules.ts files.
5.6 Migration Path: From NgModules to Standalone
The Angular team designed standalone to be incremental. You don’t have to rewrite your app all at once.
Migration strategies:
- Start with new components as standalone.
- Gradually migrate old components/modules when convenient.
- Eventually, replace
AppModulewithbootstrapApplication().
Angular provides utilities like ng generate component --standalone to make this easier.
5.7 Pros and Cons
Advantages of Standalone
- Simpler mental model (no more "where do I declare this?").
- Less boilerplate — no
NgModulefiles. - Encourages component-driven architecture.
- Direct, explicit imports (closer to how ES modules work).
Disadvantages
- Some enterprise teams already invested heavily in NgModules.
- Learning curve for developers familiar with the “old way.”
- Some third-party libraries still assume NgModules (though this is changing).
5.8 Best Practices
- For new projects, prefer standalone.
- For existing projects, mix-and-match — no need to refactor everything at once.
- Keep imports clean: only import what the component actually needs.
- Use feature folders (per-component or per-feature) to maintain structure without modules.
5.9 Summary
Standalone components represent a shift toward simplicity in Angular development. While NgModules are still supported, standalone APIs streamline the developer experience and align Angular with modern JavaScript practices.
In the next chapter, we’ll explore Signals vs. Virtual DOM, a major innovation that shows how Angular’s change detection model differs from frameworks like React — and why Angular signals are a game-changer.