Modules trong NestJS

Module là khối xây dựng cơ bản trong NestJS. Mỗi ứng dụng NestJS có ít nhất một module - Root Module (AppModule), và thường được chia nhỏ thành nhiều modules khác để tổ chức code một cách logic và có thể tái sử dụng.

Khái niệm Module

Module là một class được trang trí bằng @Module() decorator. Nó nhóm các components có liên quan lại với nhau (controllers, providers, imports, exports) thành một đơn vị cohesive.

Cấu trúc của Module

Module được định nghĩa qua đối tượng metadata có các thuộc tính sau:

1. providers

Các service hoặc injectable được NestJS tạo instance và quản lý dependency injection.

2. controllers

Các controller xử lý incoming requests và trả về responses.

3. imports

Các modules khác cần được import để sử dụng providers của chúng.

4. exports

Các providers từ module này được expose để modules khác có thể import và sử dụng.

Ví dụ thực tế

Module đơn giản

Module với imports và exports

Root Module (AppModule)

Module Exports và Reusability

Khi bạn export một provider, nó có thể được inject vào modules khác mà không cần tạo instance mới.

Global Modules

Bạn có thể tạo Global Module để tránh phải import nó ở mọi nơi. Sử dụng @Global() decorator:
Sau đó, bạn có thể sử dụng ConfigService ở bất kỳ module nào mà không cần import ConfigModule:

Dynamic Modules

Dynamic Modules cho phép bạn truyền cấu hình khi import module:

Best Practices

1. Tổ chức theo Features

Chia ứng dụng thành các modules theo tính năng (users, products, orders, …), không theo loại (controllers, services, …).

2. Dependency Management

Quản lý dependencies một cách rõ ràng. Chỉ export những gì cần thiết:

3. Tránh Circular Dependencies

Nếu ModuleA import ModuleB và ModuleB import ModuleA, sẽ gây lỗi circular dependency.

4. Sử dụng Lazy Loading (khi cần)

Để cải thiện performance, bạn có thể lazy load modules:

Lifecycle của Module

Sử dụng Lifecycle Hooks để thực hiện initialization logic:

Ví dụ Toàn Diện

Kết luận

Modules là nền tảng của kiến trúc NestJS. Chúng giúp:
  • Tổ chức code thành các đơn vị logic độc lập
  • Quản lý dependencies một cách rõ ràng
  • Tái sử dụng code giữa các phần khác nhau của ứng dụng
  • Dễ dàng testing và bảo trì
Bằng cách chia nhỏ ứng dụng thành các modules có tổ chức tốt, bạn sẽ tạo ra code dễ bảo trì, mở rộng và test hơn.