React & Next.js Topic

NestJs Modules

1. Understanding Modules

Modules are the fundamental building blocks of NestJS applications. Each module is a class annotated with @Module() decorator that organizes related functionality.

Basic Module Structure:

typescript

import { Module } from '@nestjs/common';

@Module({
  imports: [],      // Other modules to import
  controllers: [],  // Controllers in this module
  providers: [],    // Services/Providers in this module
  exports: [],      // What to make available to other modules
})
export class ModuleName {}

2. Project Structure Organization

Common Project Structures:

1. Domain-Based Structure (Recommended)

text

src/
├── modules/
│   ├── auth/
│   │   ├── auth.module.ts
│   │   ├── auth.controller.ts
│   │   ├── auth.service.ts
│   │   ├── strategies/
│   │   ├── guards/
│   │   └── dto/
│   ├── users/
│   │   ├── users.module.ts
│   │   ├── users.controller.ts
│   │   ├── users.service.ts
│   │   ├── entities/
│   │   └── dto/
│   ├── products/
│   │   ├── products.module.ts
│   │   └── ...
│   └── orders/
│       ├── orders.module.ts
│       └── ...
├── shared/
│   ├── common/
│   ├── utils/
│   ├── decorators/
│   └── interceptors/
├── config/
├── database/
└── app.module.ts

2. Layer-Based Structure

text

src/
├── controllers/
├── services/
├── repositories/
├── entities/
├── dto/
├── middleware/
└── modules/

3. Feature-Based Structure

text

src/
├── features/
│   ├── user-management/
│   ├── product-catalog/
│   └── order-processing/
├── core/
├── infrastructure/
└── api/

Recommended Structure (Domain-Driven):

typescript

// Directory structure
src/
├── common/           # Shared utilities, decorators, filters
├── config/           # Configuration files
├── database/         # Database configuration, migrations
├── modules/          # Feature modules
│   ├── auth/
│   ├── users/
│   ├── products/
│   └── orders/
├── app.module.ts     # Root module
└── main.ts          # Application entry point

3. Feature Modules

Feature modules organize code around specific features or business domains.

Creating a Feature Module:

bash

# Generate a complete module structure
nest generate module users

# Generate module with controller and service
nest generate resource users

Complete User Module Example:

typescript

// users/user.entity.ts
export class User {
  id: number;
  name: string;
  email: string;
  createdAt: Date;
}

// users/dto/create-user.dto.ts
export class CreateUserDto {
  name: string;
  email: string;
  password: string;
}

// users/dto/update-user.dto.ts
export class UpdateUserDto {
  name?: string;
  email?: string;
}

// users/users.repository.ts
import { Injectable } from '@nestjs/common';
import { User } from './user.entity';

@Injectable()
export class UsersRepository {
  private users: User[] = [];

  findAll(): User[] {
    return this.users;
  }

  findById(id: number): User {
    return this.users.find(user => user.id === id);
  }

  create(user: Partial<User>): User {
    const newUser = {
      id: this.users.length + 1,
      ...user,
      createdAt: new Date(),
    };
    this.users.push(newUser);
    return newUser;
  }
}

// users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { UsersRepository } from './users.repository';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Injectable()
export class UsersService {
  constructor(private readonly usersRepository: UsersRepository) {}

  findAll() {
    return this.usersRepository.findAll();
  }

  findOne(id: number) {
    const user = this.usersRepository.findById(id);
    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }
    return user;
  }

  create(createUserDto: CreateUserDto) {
    return this.usersRepository.create(createUserDto);
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    const user = this.findOne(id);
    return { ...user, ...updateUserDto };
  }

  remove(id: number) {
    this.findOne(id); // Verify exists
    return { message: `User ${id} deleted` };
  }
}

// users/users.controller.ts
import { 
  Controller, 
  Get, 
  Post, 
  Body, 
  Param, 
  ParseIntPipe,
  Put,
  Delete,
  HttpCode,
  HttpStatus 
} from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.findOne(id);
  }

  @Post()
  @HttpCode(HttpStatus.CREATED)
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Put(':id')
  update(
    @Param('id', ParseIntPipe) id: number,
    @Body() updateUserDto: UpdateUserDto,
  ) {
    return this.usersService.update(id, updateUserDto);
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  remove(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.remove(id);
  }
}

// users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { UsersRepository } from './users.repository';

@Module({
  controllers: [UsersController],
  providers: [UsersService, UsersRepository],
  exports: [UsersService], // Export if other modules need to use UsersService
})
export class UsersModule {}

Product Module Example:

typescript

// products/products.module.ts
import { Module } from '@nestjs/common';
import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';
import { CategoriesService } from './categories.service';
import { ProductsRepository } from './repositories/products.repository';
import { CategoriesRepository } from './repositories/categories.repository';

@Module({
  controllers: [ProductsController],
  providers: [
    ProductsService,
    CategoriesService,
    ProductsRepository,
    CategoriesRepository,
  ],
  exports: [ProductsService, CategoriesService],
})
export class ProductsModule {}

4. Shared Modules

Shared modules contain providers that need to be used across multiple feature modules.

Creating Shared Modules:

typescript

// common/common.module.ts
import { Global, Module } from '@nestjs/common';
import { LoggerService } from './logger.service';
import { ConfigService } from './config.service';
import { ValidationService } from './validation.service';

@Module({
  providers: [LoggerService, ConfigService, ValidationService],
  exports: [LoggerService, ConfigService, ValidationService],
})
export class CommonModule {}
Database Shared Module:
typescript

// database/database.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DatabaseService } from './database.service';
import { DatabaseConfig } from './database.config';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      useClass: DatabaseConfig,
    }),
  ],
  providers: [DatabaseService],
  exports: [DatabaseService, TypeOrmModule],
})
export class DatabaseModule {}

Utility Shared Module:

typescript

// utils/utils.module.ts
import { Module } from '@nestjs/common';
import { EmailService } from './email/email.service';
import { SmsService } from './sms/sms.service';
import { FileService } from './file/file.service';
import { EncryptionService } from './encryption/encryption.service';

@Module({
  providers: [EmailService, SmsService, FileService, EncryptionService],
  exports: [EmailService, SmsService, FileService, EncryptionService],
})
export class UtilsModule {}

Using Shared Modules:

typescript

// users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { CommonModule } from '../common/common.module';
import { DatabaseModule } from '../database/database.module';
import { UtilsModule } from '../utils/utils.module';

@Module({
  imports: [CommonModule, DatabaseModule, UtilsModule],
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

// orders/orders.module.ts
import { Module } from '@nestjs/common';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';
import { CommonModule } from '../common/common.module';
import { DatabaseModule } from '../database/database.module';
import { UtilsModule } from '../utils/utils.module';

@Module({
  imports: [CommonModule, DatabaseModule, UtilsModule],
  controllers: [OrdersController],
  providers: [OrdersService],
})
export class OrdersModule {}

5. Global Modules

Global modules are available throughout the entire application without needing to import them in every module.

Creating Global Modules:

typescript

// config/config.module.ts
import { Global, Module } from '@nestjs/common';
import { ConfigService } from './config.service';

@Global() // Makes this module global
@Module({
  providers: [ConfigService],
  exports: [ConfigService],
})
export class ConfigModule {}

// logger/logger.module.ts
import { Global, Module } from '@nestjs/common';
import { LoggerService } from './logger.service';

@Global()
@Module({
  providers: [LoggerService],
  exports: [LoggerService],
})
export class LoggerModule {}

Using Global Modules:

typescript

// Any module can now use ConfigService without importing ConfigModule
import { Injectable } from '@nestjs/common';
import { ConfigService } from '../config/config.service';
import { LoggerService } from '../logger/logger.service';

@Injectable()
export class UsersService {
  constructor(
    private readonly configService: ConfigService, // Available globally
    private readonly logger: LoggerService, // Available globally
  ) {
    const dbHost = this.configService.get('DATABASE_HOST');
    this.logger.log(`UsersService initialized with DB host: ${dbHost}`);
  }
}

Example: Global Cache Module:

typescript

// cache/cache.module.ts
import { Global, Module } from '@nestjs/common';
import { CacheService } from './cache.service';

@Global()
@Module({
  providers: [CacheService],
  exports: [CacheService],
})
export class CacheModule {}

// cache/cache.service.ts
import { Injectable, OnModuleDestroy } from '@nestjs/common';

@Injectable()
export class CacheService implements OnModuleDestroy {
  private cache = new Map<string, any>();

  set(key: string, value: any, ttl?: number) {
    this.cache.set(key, value);
    if (ttl) {
      setTimeout(() => this.delete(key), ttl);
    }
  }

  get<T = any>(key: string): T | undefined {
    return this.cache.get(key);
  }

  delete(key: string) {
    return this.cache.delete(key);
  }

  clear() {
    this.cache.clear();
  }

  onModuleDestroy() {
    this.clear();
  }
}

// Using cache service globally
import { Injectable } from '@nestjs/common';
import { CacheService } from '../cache/cache.service';

@Injectable()
export class ProductsService {
  constructor(private readonly cache: CacheService) {}

  async findOne(id: number) {
    const cacheKey = `product:${id}`;
    const cached = this.cache.get(cacheKey);
    
    if (cached) {
      return cached;
    }
    
    // Fetch from database
    const product = await this.fetchFromDatabase(id);
    this.cache.set(cacheKey, product, 60000); // Cache for 60 seconds
    return product;
  }
}

6. Dynamic Modules

Dynamic modules allow you to configure modules at runtime.

Creating Dynamic Modules:

typescript

// database/database.module.ts
import { DynamicModule, Module } from '@nestjs/common';
import { DatabaseService } from './database.service';

export interface DatabaseModuleOptions {
  host: string;
  port: number;
  username: string;
  password: string;
  database: string;
}

@Module({})
export class DatabaseModule {
  static forRoot(options: DatabaseModuleOptions): DynamicModule {
    return {
      module: DatabaseModule,
      providers: [
        {
          provide: 'DATABASE_OPTIONS',
          useValue: options,
        },
        DatabaseService,
      ],
      exports: [DatabaseService],
    };
  }

  static forFeature(entities: any[]): DynamicModule {
    return {
      module: DatabaseModule,
      imports: [/* register entities */],
      exports: [/* entity repositories */],
    };
  }
}

// Using dynamic module
@Module({
  imports: [
    DatabaseModule.forRoot({
      host: 'localhost',
      port: 5432,
      username: 'admin',
      password: 'secret',
      database: 'mydb',
    }),
  ],
})
export class AppModule {}

Configurable Logger Module:

typescript

// logger/logger.module.ts
import { DynamicModule, Module } from '@nestjs/common';
import { LoggerService } from './logger.service';

export interface LoggerModuleOptions {
  level: 'debug' | 'info' | 'warn' | 'error';
  format: 'json' | 'text';
}

@Module({})
export class LoggerModule {
  static forRoot(options: LoggerModuleOptions): DynamicModule {
    return {
      module: LoggerModule,
      providers: [
        {
          provide: 'LOGGER_OPTIONS',
          useValue: options,
        },
        LoggerService,
      ],
      exports: [LoggerService],
    };
  }
}

Async Configuration Module:

typescript

// config/config.module.ts
import { DynamicModule, Module } from '@nestjs/common';
import { ConfigService } from './config.service';

export interface ConfigModuleAsyncOptions {
  useFactory?: (...args: any[]) => Promise<any> | any;
  inject?: any[];
}

@Module({})
export class ConfigModule {
  static forRootAsync(options: ConfigModuleAsyncOptions): DynamicModule {
    return {
      module: ConfigModule,
      providers: [
        {
          provide: 'CONFIG_OPTIONS',
          useFactory: options.useFactory,
          inject: options.inject || [],
        },
        ConfigService,
      ],
      exports: [ConfigService],
    };
  }
}

// Using async configuration
@Module({
  imports: [
    ConfigModule.forRootAsync({
      useFactory: async (httpService: HttpService) => {
        const response = await httpService.get('/config').toPromise();
        return response.data;
      },
      inject: [HttpService],
    }),
  ],
})
export class AppModule {}

7. Avoiding Circular Dependencies

Circular dependencies occur when Module A depends on Module B, and Module B depends on Module A.

Problem Scenario:

typescript

// Circular dependency
// users.module.ts → depends on → auth.module.ts
// auth.module.ts → depends on → users.module.ts

// users.module.ts
@Module({
  imports: [AuthModule], // Depends on AuthModule
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// auth.module.ts
@Module({
  imports: [UsersModule], // Depends on UsersModule
  providers: [AuthService],
})
export class AuthModule {}

Solution 1: Use forwardRef()

typescript

// users.module.ts
import { forwardRef, Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { AuthModule } from '../auth/auth.module';

@Module({
  imports: [forwardRef(() => AuthModule)], // Forward reference
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// auth.module.ts
import { forwardRef, Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';

@Module({
  imports: [forwardRef(() => UsersModule)], // Forward reference
  providers: [AuthService],
  exports: [AuthService],
})
export class AuthModule {}

Solution 2: Create Shared Module

typescript

// shared/auth-users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { AuthService } from '../auth/auth.service';

@Module({
  providers: [UsersService, AuthService],
  exports: [UsersService, AuthService],
})
export class AuthUsersModule {}

// users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { AuthUsersModule } from '../shared/auth-users.module';

@Module({
  imports: [AuthUsersModule],
  controllers: [UsersController],
})
export class UsersModule {}

// auth.module.ts
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthUsersModule } from '../shared/auth-users.module';

@Module({
  imports: [AuthUsersModule],
  controllers: [AuthController],
})
export class AuthModule {}

Solution 3: Refactor Dependencies

typescript

// Extract common functionality to a separate module
// common/security.module.ts
import { Module } from '@nestjs/common';
import { PasswordService } from './password.service';
import { TokenService } from './token.service';

@Module({
  providers: [PasswordService, TokenService],
  exports: [PasswordService, TokenService],
})
export class SecurityModule {}

// users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { SecurityModule } from '../common/security.module';

@Module({
  imports: [SecurityModule],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

// auth.module.ts
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { SecurityModule } from '../common/security.module';

@Module({
  imports: [UsersModule, SecurityModule], // No circular dependency
  providers: [AuthService],
})
export class AuthModule {}

Solution 4: Use Module Reference

typescript

// auth.service.ts
import { Injectable, Inject, forwardRef } from '@nestjs/common';

@Injectable()
export class AuthService {
  constructor(
    @Inject(forwardRef(() => UsersService))
    private readonly usersService: UsersService,
  ) {}
}

8. Module Re-exporting

Re-export modules to simplify imports.

Basic Re-exporting:

typescript

// shared/shared.module.ts
import { Module } from '@nestjs/common';
import { CommonModule } from '../common/common.module';
import { DatabaseModule } from '../database/database.module';
import { UtilsModule } from '../utils/utils.module';

@Module({
  imports: [CommonModule, DatabaseModule, UtilsModule],
  exports: [CommonModule, DatabaseModule, UtilsModule],
})
export class SharedModule {}

// Now other modules only need to import SharedModule
@Module({
  imports: [SharedModule], // Import all shared modules at once
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

Feature Aggregation Module:

typescript

// features/features.module.ts
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth/auth.module';
import { UsersModule } from '../users/users.module';
import { ProductsModule } from '../products/products.module';
import { OrdersModule } from '../orders/orders.module';

@Module({
  imports: [AuthModule, UsersModule, ProductsModule, OrdersModule],
  exports: [AuthModule, UsersModule, ProductsModule, OrdersModule],
})
export class FeaturesModule {}

// app.module.ts
import { Module } from '@nestjs/common';
import { FeaturesModule } from './features/features.module';

@Module({
  imports: [FeaturesModule],
})
export class AppModule {}

9. Best Practices & Patterns

1. Lazy Loading Modules

typescript

// app.module.ts
import { Module } from '@nestjs/common';

@Module({
  imports: [
    {
      module: UsersModule,
      // Lazy load conditionally
      condition: process.env.ENABLE_USERS_MODULE === 'true',
    },
    {
      module: AdminModule,
      // Load only in admin mode
      condition: process.env.ADMIN_MODE === 'true',
    },
  ],
})
export class AppModule {}

2. Module Facade Pattern

typescript

// payment/payment.module.ts
import { Module } from '@nestjs/common';
import { PaymentController } from './payment.controller';
import { PaymentFacadeService } from './payment-facade.service';
import { StripeService } from './providers/stripe.service';
import { PayPalService } from './providers/paypal.service';
import { BankTransferService } from './providers/bank-transfer.service';

@Module({
  controllers: [PaymentController],
  providers: [
    PaymentFacadeService,
    StripeService,
    PayPalService,
    BankTransferService,
  ],
  exports: [PaymentFacadeService],
})
export class PaymentModule {}

// payment/payment-facade.service.ts
import { Injectable } from '@nestjs/common';
import { StripeService } from './providers/stripe.service';
import { PayPalService } from './providers/paypal.service';

@Injectable()
export class PaymentFacadeService {
  constructor(
    private readonly stripeService: StripeService,
    private readonly paypalService: PayPalService,
  ) {}

  async processPayment(method: string, amount: number) {
    switch (method) {
      case 'stripe':
        return this.stripeService.charge(amount);
      case 'paypal':
        return this.paypalService.createPayment(amount);
      default:
        throw new Error('Unsupported payment method');
    }
  }
}

3. Plugin Modules

typescript

// plugins/analytics/analytics.module.ts
import { DynamicModule, Module } from '@nestjs/common';

export interface AnalyticsModuleOptions {
  apiKey: string;
  enabled: boolean;
}

@Module({})
export class AnalyticsModule {
  static forRoot(options: AnalyticsModuleOptions): DynamicModule {
    if (!options.enabled) {
      return {
        module: AnalyticsModule,
        providers: [],
      };
    }

    return {
      module: AnalyticsModule,
      providers: [
        {
          provide: 'ANALYTICS_OPTIONS',
          useValue: options,
        },
        AnalyticsService,
      ],
      exports: [AnalyticsService],
    };
  }
}

4. Module Configuration Pattern

typescript

// modules/configurable-module.ts
import { DynamicModule, Module } from '@nestjs/common';

export interface ConfigurableModuleOptions {
  featureFlag: boolean;
  maxRetries?: number;
  timeout?: number;
}

export const DEFAULT_OPTIONS: Partial<ConfigurableModuleOptions> = {
  maxRetries: 3,
  timeout: 5000,
};

@Module({})
export class ConfigurableModule {
  static forRoot(options: ConfigurableModuleOptions): DynamicModule {
    const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
    
    return {
      module: ConfigurableModule,
      providers: [
        {
          provide: 'MODULE_OPTIONS',
          useValue: mergedOptions,
        },
        ConfigurableService,
      ],
      exports: [ConfigurableService],
    };
  }
}

5. Complete E-commerce Application Structure

typescript

// app.module.ts (Root Module)
import { Module } from '@nestjs/common';
import { ConfigModule } from './config/config.module';
import { DatabaseModule } from './database/database.module';
import { CacheModule } from './cache/cache.module';
import { AuthModule } from './modules/auth/auth.module';
import { UsersModule } from './modules/users/users.module';
import { ProductsModule } from './modules/products/products.module';
import { OrdersModule } from './modules/orders/orders.module';
import { SharedModule } from './shared/shared.module';

@Module({
  imports: [
    // Global modules
    ConfigModule.forRoot(),
    DatabaseModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: parseInt(process.env.DB_PORT),
    }),
    CacheModule,
    
    // Feature modules
    AuthModule,
    UsersModule,
    ProductsModule,
    OrdersModule,
    
    // Shared utilities
    SharedModule,
  ],
})
export class AppModule {}

// modules/orders/orders.module.ts
import { Module, forwardRef } from '@nestjs/common';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';
import { OrderItemsService } from './order-items.service';
import { PaymentsModule } from '../payments/payments.module';
import { ProductsModule } from '../products/products.module';
import { UsersModule } from '../users/users.module';
import { ShippingModule } from '../shipping/shipping.module';
import { EmailModule } from '../../shared/email/email.module';

@Module({
  imports: [
    forwardRef(() => PaymentsModule), // Use forwardRef to avoid circular deps
    ProductsModule,
    UsersModule,
    ShippingModule,
    EmailModule,
  ],
  controllers: [OrdersController],
  providers: [OrdersService, OrderItemsService],
  exports: [OrdersService],
})
export class OrdersModule {}

// modules/products/products.module.ts
import { Module } from '@nestjs/common';
import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';
import { CategoriesService } from './categories.service';
import { InventoryService } from './inventory.service';
import { ReviewsService } from './reviews.service';
import { DatabaseModule } from '../../database/database.module';
import { CacheModule } from '../../cache/cache.module';

@Module({
  imports: [DatabaseModule, CacheModule],
  controllers: [ProductsController],
  providers: [
    ProductsService,
    CategoriesService,
    InventoryService,
    ReviewsService,
  ],
  exports: [
    ProductsService,
    CategoriesService,
    InventoryService,
  ],
})
export class ProductsModule {}

// shared/shared.module.ts
import { Global, Module } from '@nestjs/common';
import { LoggerService } from './logger/logger.service';
import { ValidationService } from './validation/validation.service';
import { EncryptionService } from './encryption/encryption.service';
import { FileService } from './file/file.service';
import { EmailService } from './email/email.service';

@Global() // Make available globally
@Module({
  providers: [
    LoggerService,
    ValidationService,
    EncryptionService,
    FileService,
    EmailService,
  ],
  exports: [
    LoggerService,
    ValidationService,
    EncryptionService,
    FileService,
    EmailService,
  ],
})
export class SharedModule {}

Module Organization Rules:

  1. Single Responsibility: Each module should handle one domain/feature

  2. Explicit Exports: Only export what other modules need

  3. Avoid Deep Nesting: Keep module hierarchy flat

  4. Use Shared Modules: For cross-cutting concerns

  5. Global Modules Sparingly: Only for truly global services

  6. ForwardRef for Circular Dependencies: Use when necessary

  7. Dynamic Modules for Configuration: When runtime configuration is needed

  8. Re-export Aggregately: Simplify imports with shared module exports

  9. Feature Flags: Use conditional loading for optional features

  10. Testability: Design modules to be easily testable in isolation

This modular approach ensures your NestJS application is maintainable, scalable, and easy to understand as it grows.

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?