Trong NestJS – một framework mạnh mẽ và có cấu trúc tốt của Node.js – Module là đơn vị tổ chức cốt lõi, nơi bạn tập hợp các thành phần có liên quan để tạo nên một tính năng hoàn chỉnh.

Trong bài viết này, chúng ta sẽ đào sâu vào 4 khái niệm quan trọng nhất trong mỗi module của NestJS:

  • imports

  • exports

  • controllers

  • providers

NestJS Module là gì?

Một Module trong NestJS chỉ đơn giản là một class được trang trí bằng decorator @Module(), và có thể chứa:

  • các controller

  • các provider (service, repository, factory, v.v.)

  • các module khác được import vào

  • các thành phần được export ra để module khác dùng được

@Module({
  imports: [...],
  controllers: [...],
  providers: [...],
  exports: [...]
})
export class YourModule {}

1.  imports – Nhập module khác để dùng

Trong thực tế, bạn sẽ cần chia nhỏ ứng dụng thành nhiều module và tái sử dụng logic giữa chúng.

@Module({
  imports: [
    CqrsModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET || 'secretKey',
      signOptions: { expiresIn: '1d' },
    }),
    RedisModule,
    QueueModule,
  ]
})

Khi bạn import một module, bạn có thể sử dụng những provider mà module đó export ra.

@Module({
  providers: [RedisService],
  exports: [RedisService]
})
export class RedisModule {}

Nếu module khác muốn dùng RedisService, chỉ cần imports: [RedisModule].

2. controllers – Định nghĩa các route nhận request

Controllers chịu trách nhiệm tiếp nhận và xử lý HTTP request (hoặc WebSocket/gRPC tùy config).

Ví dụ:

@Controller('users')
export class UserController {
  constructor(private userService: UserService) {}

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

Controller sẽ được khai báo trong:

@Module({
  controllers: [UserController]
})

Nếu không khai báo trong này, NestJs sẽ không biết bạn đang định nghĩa controller nào cho api nào.

3. providers – Cung cấp service, repository, factory,…

Đây là bộ não xử lý logic nghiệp vụ, ví dụ như:

@Injectable()
export class UserService {
  findAll() {
    return [{ name: 'John Doe' }];
  }
}

Muốn NestJS inject được class này, bạn phải khai báo trong providers:

@Module({
  providers: [UserService]
})

Provider có thể là @Injectable(), useClass, useFactory, useValue, useExisting.

4. exports – Xuất provider ra ngoài cho module khác dùng

Giống như public trong OOP, nếu bạn muốn module khác dùng được UserService, bạn phải export nó.

@Module({
  providers: [UserService],
  exports: [UserService]
})
export class UserModule {}

Module khác chỉ cần:

@Module({
  imports: [UserModule]
})

Là có thể inject được UserService.

Ví dụ thực tế tổng hợp

@Module({
  imports: [DatabaseModule],
  controllers: [UserController],
  providers: [UserService, UserRepository],
  exports: [UserService]
})
export class UserModule {}
  • UserService có thể dùng ở nơi khác nếu UserModule được import.

  • UserController định tuyến HTTP /users.

  • UserRepository là provider nội bộ hỗ trợ UserService.

  • DatabaseModule có thể cung cấp Prisma hoặc TypeORM cho repository.

Không export provider thì sao?

→ Module khác sẽ không inject được, dù bạn có imports.

Provider có cần khai báo lại trong controller không?

Không. NestJS sẽ inject tự động nếu bạn đã khai báo trong providers.

Có thể export controller không?

Không. controllers chỉ dùng trong chính module đó.