Tại sao không dùng Express mà lại là NestJS?
Nếu bạn đã quen với Node.js, chắc chắn Express là cái tên đầu tiên xuất hiện trong đầu. Express giống như một chiếc xe máy độ – bạn có thể gắn bất cứ thứ gì lên đó, tự do sáng tạo. Nhưng khi dự án lớn dần, sự tự do đó biến thành một bãi rác khổng lồ nếu không có kỷ luật. Mình từng refactor codebase 50.000 lines của một startup viết bằng Express thuần.
Đó thực sự là một cơn ác mộng. Mỗi dev viết một kiểu. Logic nằm rải rác từ Controller đến Middleware. Đôi khi, mình mất tới 4 tiếng chỉ để tìm ra một lỗi logic nhỏ xíu.
NestJS xuất hiện để giải quyết vấn đề này. Nó không bắt bạn học lại Node.js từ đầu. Thay vào đó, nó cung cấp một bộ khung (framework) cực kỳ chặt chẽ dựa trên TypeScript. Nếu Express là một cái chợ tự phát, thì NestJS chính là một siêu thị được quy hoạch bài bản. Mọi thứ từ Module, Controller đến Service đều có vị trí rõ ràng.
Ưu và nhược điểm khi đưa NestJS vào dự án thực tế
Trước khi quyết định “đổi đời” sang NestJS, chúng ta cần nhìn thẳng vào sự thật. Không có công nghệ nào là hoàn hảo. Chỉ có công nghệ phù hợp hay không mà thôi.
Ưu điểm:
- Kiến trúc Module: Chia nhỏ dự án thành từng phần độc lập. Việc mở rộng quy mô trở nên cực kỳ dễ dàng.
- Dependency Injection (DI): Tính năng này giúp việc viết Unit Test cực kỳ nhàn. Bạn có thể mock dữ liệu chỉ trong vài dòng code.
- Tài liệu xịn: Docs của NestJS thuộc hàng top. Gần như mọi lỗi bạn gặp đã có sẵn câu trả lời trên Stack Overflow.
- Hỗ trợ tận răng: Từ GraphQL, WebSockets đến Microservices, NestJS đều có sẵn thư viện tích hợp.
Nhược điểm:
- Rào cản ban đầu: Bạn sẽ mất khoảng 1-2 tuần đầu để làm quen với Decorators (@Controller, @Injectable) và khái niệm DI.
- Tốn RAM hơn: Vì chứa nhiều lớp trừu tượng, một instance NestJS mới khởi tạo có thể ngốn ~60-80MB RAM, trong khi Express chỉ khoảng ~30MB. Tuy nhiên, con số này không đáng kể với server hiện đại.
Lựa chọn PostgreSQL cho các hệ thống cần độ chính xác cao
Tại sao lại là PostgreSQL mà không phải MongoDB? Khi làm việc với các hệ thống cần sự chính xác tuyệt đối như số dư ví điện tử hay quản lý tồn kho, mình luôn chọn PostgreSQL. Tính nhất quán (ACID) của nó là thứ mà các database NoSQL khó lòng bì kịp.
NestJS mạnh về cấu trúc code. PostgreSQL mạnh về cấu trúc dữ liệu. Khi kết hợp lại, bạn sẽ có một nền tảng vững như bàn thạch. Kinh nghiệm của mình là: Hãy đầu tư vào kiến trúc ngay từ ngày đầu để tránh những đêm OT (Overtime) vô nghĩa sau này.
Bắt tay vào xây dựng: Từng bước triển khai
Đầu tiên, hãy cài đặt Node.js và một instance PostgreSQL. Bạn có thể dùng Docker để dựng database chỉ trong 30 giây.
1. Khởi tạo Project
Chúng ta sẽ sử dụng Nest CLI để tạo boilerplate cực nhanh.
npm i -g @nestjs/cli
nest new my-api-project
Chọn npm hoặc yarn tùy sở thích. Sau vài phút, bạn đã có một cấu trúc folder chuẩn chỉnh.
2. Kết nối Database PostgreSQL
Chúng ta sẽ sử dụng TypeORM để thao tác với database dưới dạng Object. Hãy cài đặt các package sau:
npm install --save @nestjs/typeorm typeorm pg
Mở file src/app.module.ts và điền thông số kết nối:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'yourpassword',
database: 'test_db',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true, // Cẩn thận: Chỉ dùng khi dev, tuyệt đối không dùng cho production!
}),
],
})
export class AppModule {}
3. Tạo Resource ‘Posts’ trong 1 nốt nhạc
Thay vì tạo tay từng file, hãy để CLI làm hộ bạn:
nest generate resource posts
Lệnh này giúp bạn tiết kiệm ít nhất 15 phút gõ boilerplate code. Nó tự tạo luôn Controller, Service và DTO.
4. Chặn đứng dữ liệu rác bằng Validation
Đây là bước then chốt. Đừng bao giờ tin tưởng dữ liệu từ phía Client. Thay vì viết if/else dài dằng dặc, hãy dùng class-validator.
npm install --save class-validator class-transformer
Kích hoạt tính năng này tại main.ts:
app.useGlobalPipes(new ValidationPipe());
Bây giờ, hãy vào file DTO để định nghĩa luật chơi:
import { IsString, MinLength, IsNotEmpty } from 'class-validator';
export class CreatePostDto {
@IsNotEmpty({ message: 'Tiêu đề không được để trống' })
@IsString()
@MinLength(10, { message: 'Tiêu đề phải dài từ 10 ký tự trở lên' })
title: string;
@IsNotEmpty()
content: string;
}
Kết quả là gì? Nếu Client gửi thiếu dữ liệu, API sẽ tự động trả về lỗi 400 kèm thông báo cực kỳ chi tiết. Bạn không cần viết thêm một dòng logic check lỗi nào trong Controller.
Lời kết
Xây dựng hệ thống không khó. Giữ cho nó sạch sẽ khi phình to mới là thách thức. NestJS và PostgreSQL là bộ đôi hoàn hảo để bạn bắt đầu sự nghiệp Backend chuyên nghiệp. Đừng ngại tốn thời gian học kiến trúc. Nó sẽ cứu rỗi bạn khỏi những đống code rối rắm trong tương lai.
Anh em cứ thử áp dụng vào dự án thực tế xem. Chắc chắn code sẽ “sang chảnh” và dễ bảo trì hơn nhiều. Nếu gặp lỗi khi setup, cứ để lại bình luận phía dưới nhé!

