Angular Standalone Components: Do We Still Need Modules?

Hero image for Angular Standalone Components: Do We Still Need Modules? Image by Dmitry Kropachev.
Hero image for 'Angular Standalone Components: Do We Still Need Modules?' Image by Dmitry Kropachev.

Angular standalone components tend to trigger one slightly misleading question: are NgModules dead? It's understandable, because standalone APIs change the shape of everyday Angular development quite a lot. Still, the more useful question isn't whether modules have vanished, but whether they still solve a problem we genuinely have.

For most new application code, standalone components give us a much cleaner starting point. They reduce ceremony, make dependencies more explicit, and fit naturally with lazy loading. That said, Angular did not accidentally invent NgModules in the first place. They existed to group declarations, providers, and imports at a time when the framework needed a heavier structural unit. Understanding that history helps us decide how much of it we still need.


Why Standalone Components Changed the Conversation

NgModules used to be the frameworklevel way to declare which components, directives, and pipes belonged together. They also controlled imports and, in many projects, became the de facto feature boundary. That worked, but it often meant spreading one feature across several files before we had written much logic at all.

Standalone components reverse that default. A component can now declare its own dependencies directly, which makes the boundary easier to read. In a mature codebase, that isn't just nicer syntax. It means we can usually see what a component needs without hopping through a module tree first.

Why This Matters for Architecture

A smaller unit of composition usually makes lazy loading, testing, and migration simpler. Instead of building a feature module first and then hanging components off it, we can let routes, providers, and components express the feature boundary more directly. That's especially useful in applications that are evolving gradually rather than being rebuilt from scratch.


A Practical, Standalone Setup

A modern Angular application can bootstrap without an application module at all. The dependencies live where they are used, and routing can lazyload standalone pages directly.

import { bootstrapApplication } from '@angular/platform-browser';import { Component } from '@angular/core';import { provideRouter, RouterOutlet, Routes } from '@angular/router';import { NgIf } from '@angular/common';const routes: Routes = [  {    path: '',    loadComponent: () => import('./home.component').then((module) => module.HomeComponent),  },];@Component({  selector: 'app-root',  standalone: true,  imports: [RouterOutlet, NgIf],  template: `    <main>      <h1>Angular Standalone</h1>      <router-outlet />    </main>  `,})export class AppComponent {}void bootstrapApplication(AppComponent, {  providers: [provideRouter(routes)],});

The important detail here isn't just that the code is shorter. The dependencies are local and obvious. That makes components easier to test, and it makes feature boundaries much easier to move around later.


Where Ngmodules Still Remain Useful

It's easy to think that standalone components remove every remaining use for modules. In practice, modules still appear in library compatibility layers, older codebases, and some thirdparty integration stories. They are no longer the default unit we have to reach for, but they have not become invalid overnight.

Migration is also rarely allornothing. Angular explicitly supports interoperation between standalone and modulebased code, which means we can modernise feature by feature. That's usually the pragmatic path in a working product, because it avoids turning an architectural improvement into an expensive rewrite programme.


What a Sensible Migration Strategy Looks Like

The strongest migrations start at route boundaries or isolated features. A leaf page, settings area, or new admin workflow is often a better first candidate than the application shell. That gives us enough room to validate the pattern without forcing every shared concern to move on day one.

If we mix standalone and modulebased code for a period, the main job is clarity. We should document which style is the default for new work, where compatibility wrappers still exist, and which feature areas are being migrated next. That keeps the codebase coherent rather than accidentally hybrid.


How This Holds up in a Real Codebase

Standalone components are easier to test because setup can import the component and its direct dependencies without the extra indirection of a feature module. They also make routelevel lazy loading much more straightforward in modern Angular APIs, which is where the architectural gain tends to show up.

Those gains are real, but they only show up if we keep boundaries clean. Replacing modules with one giant component import list would not be much of an improvement. The real value comes from making features smaller, clearer, and easier to evolve.

For the exact Angular behaviour discussed here, the official guides below are the useful ones to keep open:


Wrapping up

Standalone components give Angular a cleaner default shape, but the useful lesson isn't that the older structure was foolish. It's that the framework has become more direct about where boundaries really belong.

Key Takeaways

  • Standalone components are the modern default for most new Angular application code.
  • NgModules still exist, but they are no longer the only sensible way to organise features.
  • The real benefit is clearer boundaries, better lazy loading, and simpler test setup.

Standalone components matter because they let Angular applications describe dependencies more directly. Once we treat that as an architectural improvement rather than a fashion change, the migration path usually becomes much easier to judge.


Categories:

  1. Angular
  2. Development
  3. Front‑End Development
  4. Guides
  5. JavaScript