Interview answer drill

Use this Angular interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.

What problems do NgModules solve that standalone components don’t?Frontend interview answer

HighIntermediateAngular
Interview focus

This Angular interview question tests whether you can explain Do you still need NgModules with standalone Angular components, connect it to production trade-offs, and handle common follow-up questions.

  • Do you still need NgModules with standalone Angular components explanation without falling back to memorized docs wording
  • Modules and Standalone reasoning, edge cases, and production failure modes
  • How you would answer the most likely Angular interview follow-up
Practice more Angular interview questions
Interview quick answer

Standalone components remove the need for NgModules for most app composition, routing, and DI setup. NgModules still solve a few practical problems: packaging legacy (non-standalone) declarations, consuming module-based third-party libraries (forRoot/forChild), and providing a single import/export “bundle” boundary that some teams and libraries still rely on. The senior distinction is module compatibility versus module necessity.

Full interview answer

Overview

Standalone components shift Angular’s "template dependency scope" from @NgModule to the component itself (imports on the component). For modern apps, that removes most reasons to create feature/shared modules.

NgModules still matter mainly as a packaging + compatibility layer for legacy declarables and module-based libraries/config APIs.

Problem / need

NgModule solves it by...

Standalone status

Using non-standalone directives/pipes/components (legacy code or older libs)

Declaring them once and exporting them via a module

Standalone cannot directly import non-standalone declarables; you import the NgModule that exports them.

Module-style library configuration (forRoot/forChild patterns)

Returning ModuleWithProviders and wiring providers through module imports

Standalone supports this mostly via importProvidersFrom(SomeModule.forRoot(...)), but the library still forces the NgModule shape.

Single “bundle import” for a large set of template dependencies

One SharedModule re-exports many imports/exports so feature code imports one thing

Standalone can mimic with a shared array/const, but there’s no first-class “export scope” container like NgModule exports.

Gradual migration in an existing NgModule app

You can convert leaf components to standalone while keeping module boundaries intact

Standalone is great for incremental migration, but NgModules remain the glue during the transition.

Team convention: explicit public API surface (exports) for a domain

Exports define what the rest of the app can use from that domain

Standalone relies on regular TS exports + per-component imports; you lose the explicit “exports list” mechanism.

Where NgModules still provide value in a standalone-first Angular world
TYPESCRIPT
// legacy-shared.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { LegacyHighlightDirective } from './legacy-highlight.directive';
import { LegacyDatePipe } from './legacy-date.pipe';

@NgModule({
  declarations: [LegacyHighlightDirective, LegacyDatePipe],
  imports: [CommonModule],
  exports: [CommonModule, LegacyHighlightDirective, LegacyDatePipe]
})
export class LegacySharedModule {}
                  
TYPESCRIPT
// standalone component consuming legacy declarations via NgModule
import { Component } from '@angular/core';
import { LegacySharedModule } from './legacy-shared.module';

@Component({
  standalone: true,
  selector: 'app-user-card',
  imports: [LegacySharedModule],
  template: `
    <div legacyHighlight>
      {{ today | legacyDate }}
    </div>
  `
})
export class UserCardComponent {
  today = new Date();
}
                  

If you’re fully standalone, do this instead

Why it’s the equivalent

Create reusable import bundles as constants (not modules)

Gives you “one name” to import across many standalone components without an NgModule exports list.

Prefer provider functions (provideRouter, provideHttpClient, etc.)

Moves app configuration to bootstrap/route providers and reduces NgModule-only configuration patterns.

Standalone alternatives to common “SharedModule” patterns
TYPESCRIPT
// Greenfield standalone feature: no new feature NgModule required
import { Component } from '@angular/core';
import { NgIf } from '@angular/common';
import { ProductCardComponent } from './product-card.component';

@Component({
  standalone: true,
  selector: 'app-product-list-page',
  imports: [NgIf, ProductCardComponent],
  template: `
    <app-product-card *ngIf="featured" [product]="featured"></app-product-card>
  `
})
export class ProductListPage {
  featured = { id: 1, name: 'Keyboard' };
}

// Legacy/module-shaped library API: still compatible, but only because the library forces it
import { bootstrapApplication, importProvidersFrom } from '@angular/core';
import { TranslateModule } from 'some-translate-lib';

bootstrapApplication(ProductListPage, {
  providers: [
    importProvidersFrom(TranslateModule.forRoot({ defaultLang: 'en' }))
  ]
});
                  
TYPESCRIPT
// Module-based library config still shows up a lot
import { bootstrapApplication, importProvidersFrom } from '@angular/core';
import { AppComponent } from './app.component';
import { TranslateModule } from 'some-translate-lib';

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(TranslateModule.forRoot({ defaultLang: 'en' }))
  ]
});
                  

Situation

Senior choice

Why

New app with standalone-ready libraries

Create no new NgModule

Direct component imports + provider functions already cover normal composition and DI setup.

Legacy directives/pipes/components still need declarations/exports

Keep or bridge an NgModule

Standalone cannot directly import non-standalone declarables.

A library still exposes forRoot/ModuleWithProviders

Use importProvidersFrom(...)

That is library compatibility, not proof that your feature still needs its own NgModule.

You want one reusable import bundle

Use TS constants/barrels first

Packaging convenience is not the same thing as a required Angular module boundary.

Decision matrix: when NgModules are still solving a real problem

Sharp distinction

Module compatibility means Angular can still interoperate with a module-shaped dependency or legacy declarable. Module necessity means your own new feature still needs a fresh NgModule. In modern greenfield apps, the first can remain true while the second is usually false.

Summary

Standalone components cover most of what NgModules were used for (composition, routing, DI setup). NgModules still “win” mainly for legacy/non-standalone declarations and module-shaped third-party APIs (especially forRoot/forChild). In a greenfield app with modern libs, you usually don’t need to write new NgModules.

Similar questions
Guides
Preparing for interviews?

Use this as one explanation rep, then continue with the Angular interview questions cluster or a guided prep path.