Angular  

Understanding Angular Modules, Lazy Loading, and Folder Structure Best Practices

When building small Angular apps, everything feels simple. But as your application grows—more features, more developers, more screens—your code structure either becomes organized… or chaos.

This article will help you avoid chaos.

We will cover:

  • What Angular Modules are (and why they matter)

  • Types of Angular Modules

  • Lazy Loading (with real examples)

  • Folder structure best practices used in real enterprise applications

1️⃣ What Are Angular Modules?

An Angular Module (NgModule) is a container that groups related components, directives, pipes, and services. It acts like a “room” in a house — every feature gets its own space.

A basic module looks like:

@NgModule({
  declarations: [HomeComponent],
  imports: [CommonModule],
  exports: [HomeComponent]
})
export class HomeModule { }

Why do modules exist?

PurposeMeaning
OrganizationKeep related files together (like features)
ReusabilityShare components across modules
PerformanceEnable Lazy Loading
ScalabilityManage a growing enterprise app

2️⃣ Types of Angular Modules

Not all modules serve the same purpose. Below are the common categories used by professionals:

Module TypePurposeExample
Root ModuleApp entry pointAppModule
Feature ModuleOne feature, one moduleUsersModule, OrdersModule
Shared ModuleComponents used across featuresButtons, Tables, Pipes
Core ModuleSingleton services (auth, API)AuthService, HttpInterceptor

Example Folder with Modules

src/app/
 ├── app.module.ts
 ├── core/
 │    └── core.module.ts
 ├── shared/
 │    └── shared.module.ts
 ├── features/
 │    ├── users/
 │    │    ├── users.module.ts
 │    ├── orders/
 │    │    ├── orders.module.ts

3️⃣ Lazy Loading — The Game Changer

Lazy loading means loading modules only when needed, instead of loading everything at startup.

👉 Result? Faster performance and better UX.

Without Lazy Loading (Bad for large apps)

@NgModule({
  imports: [
    BrowserModule,
    UsersModule,
    OrdersModule
  ]
})
export class AppModule {}

Everything loads upfront — even if the user never visits /users.

With Lazy Loading (Better Approach)

In app-routing.module.ts:

const routes: Routes = [
  {
    path: 'users',
    loadChildren: () =>
      import('./features/users/users.module').then(m => m.UsersModule)
  }
];

Angular will now load the UsersModule ONLY when the user opens /users.

Example of Feature Module Routing

users-routing.module.ts:

const routes: Routes = [
  { path: '', component: UsersListComponent },
  { path: 'add', component: AddUserComponent }
];

When Should You Use Lazy Loading?

ScenarioShould Lazy Load?
Feature with multiple components & separate screens (large)✅ YES
Shared utilities or common UI❌ NO
Admin sections not accessed regularly✅ YES
Small feature with 1 component❌ Optional

4️⃣ Folder Structure Best Practices

The best structure depends on project size. Here's a scalable and enterprise-friendly example:

src/app/
 ├── core/
 │   ├── guards/
 │   ├── interceptors/
 │   ├── services/
 │   └── core.module.ts
 ├── shared/
 │   ├── components/
 │   ├── pipes/
 │   ├── directives/
 │   └── shared.module.ts
 ├── features/
 │   ├── auth/
 │   │   ├── login/
 │   │   ├── register/
 │   │   └── auth.module.ts
 │   ├── dashboard/
 │   │   └── dashboard.module.ts
 ├── app-routing.module.ts
 └── app.module.ts

Why this structure works?

  • Clear separation of responsibilities

  • Easy navigation for developers

  • Supports lazy loading and reusability

  • Scales with project size

5️⃣ Common Mistakes to Avoid

MistakeFix
Putting everything in AppModuleCreate modules per feature
Importing SharedModule everywhereOnly import where needed
Storing services in feature modules incorrectlyMove singleton services to CoreModule
Not wildcard lazy-loaded modulesVerify routing structure

Quick Recap

✔ Angular modules organize and scale your application
✔ Feature modules help structure major functionalities
✔ Lazy loading improves performance
✔ A clean folder structure makes your code maintainable

Final Thought

Treat your Angular application like a city.
Modules are districts. Lazy loading is the highway system deciding which district opens when needed.