NestJS là một framework Node.js mạnh mẽ và linh hoạt được xây dựng trên cơ sở TypeScript. Với mục tiêu tạo ra các ứng dụng server-side hiệu quả và dễ bảo trì, NestJS cung cấp một kiến trúc modular và sử dụng nguyên tắc Dependency Injection để quản lý các thành phần của ứng dụng.
NestJS kết hợp các khái niệm từ các framework nổi tiếng như Angular và Express để cung cấp một cách tiếp cận tốt hơn trong việc xây dựng ứng dụng server-side. Với NestJS, bạn có thể sử dụng decorators để định nghĩa các module, controller và provider, giúp tăng tính rõ ràng và tái sử dụng trong mã nguồn của bạn.
Một trong những đặc điểm nổi bật của NestJS là hỗ trợ cho TypeScript. Với TypeScript, bạn có thể tận dụng các tính năng của ngôn ngữ này như kiểu tĩnh, kiểm tra lỗi tại thời điểm biên dịch và thông tin IntelliSense mạnh mẽ. Điều này giúp tăng tính ổn định và sự tự tin trong quá trình phát triển ứng dụng.
NestJS cũng cung cấp các tính năng như Dependency Injection, Middleware, Pipes, Guards, Interceptors và Exception Filters để tạo ra các ứng dụng mạnh mẽ, linh hoạt và dễ bảo trì. Nó hỗ trợ các cơ sở dữ liệu phổ biến như MySQL, PostgreSQL, MongoDB và Redis, cũng như cung cấp tích hợp dễ dàng với các công nghệ khác như GraphQL và WebSocket.
Xem thêm Điều kiện WHERE trong SQL
Với khả năng xây dựng ứng dụng nhất quán, dễ mở rộng và kiểm thử, NestJS đã trở thành một lựa chọn phổ biến cho việc phát triển ứng dụng server-side trong cộng đồng Node.js. Nó cung cấp một cách tiếp cận hiện đại và chuẩn mực để xây dựng các dự án có quy mô lớn, cung cấp hiệu suất cao và độ tin cậy.
Cài đặt và cấu hình NestJS
Để cài đặt và cấu hình NestJS, bạn có thể tuân theo các bước sau:
Bước 1: Cài đặt Node.js và npm
- Trước tiên, hãy đảm bảo rằng bạn đã cài đặt Node.js và npm trên máy tính của mình. Bạn có thể tải xuống và cài đặt Node.js từ trang chủ của Node.js (https://nodejs.org).
Bước 2: Tạo dự án NestJS mới
- Mở terminal hoặc command prompt và di chuyển đến thư mục mà bạn muốn tạo dự án NestJS.
- Chạy lệnh sau để tạo dự án mới bằng Nest CLI:arduinoCopy code
npx nest new project-name
- Thay “project-name” bằng tên của dự án bạn muốn tạo. Nest CLI sẽ tạo ra cấu trúc dự án NestJS cơ bản cho bạn.
Bước 3: Cấu hình và chạy ứng dụng
- Di chuyển vào thư mục dự án mới bằng cách chạy lệnh:
cd project-name
- Bây giờ bạn có thể chạy ứng dụng NestJS bằng lệnh:
npm run start
- Ứng dụng NestJS sẽ được chạy trên cổng mặc định 3000 (hoặc cổng khác nếu đã được cấu hình). Bạn có thể truy cập ứng dụng của mình bằng địa chỉ http://localhost:3000 trên trình duyệt.
Bước 4: Thay đổi cấu hình và cài đặt thêm modules
- Bạn có thể chỉnh sửa cấu hình của ứng dụng trong tệp “src/main.ts”. Đây là nơi bạn có thể thay đổi cổng và các cài đặt khác của ứng dụng NestJS.
- Để cài đặt thêm modules, bạn có thể sử dụng Nest CLI hoặc cài đặt chúng thủ công thông qua npm. Ví dụ, để cài đặt module TypeORM, bạn có thể chạy lệnh:
npm install @nestjs/typeorm typeorm mysql
- Sau khi cài đặt module, bạn cần import nó vào ứng dụng của mình và cấu hình tương ứng.
Đó là quy trình cơ bản để cài đặt và cấu hình NestJS. Từ đây, bạn có thể tiếp tục xây dựng ứng dụng của mình, tạo controllers, services và các thành phần khác để phát triển ứng dụng NestJS đầy đủ.
Xem thêm Kiểm tra lỗ hổng bảo mật SQL injection trong PostgreSQL
Xây dựng API với NestJS
Để xây dựng API với NestJS, bạn có thể tuân theo các bước sau:
Bước 1: Tạo module
- Mở terminal hoặc command prompt và di chuyển đến thư mục dự án NestJS.
- Chạy lệnh sau để tạo một module mới:
nest generate module module-name
- Thay “module-name” bằng tên của module bạn muốn tạo. Nest CLI sẽ tạo ra một thư mục mới chứa các tệp tin cần thiết cho module.
Bước 2: Tạo controller
- Chạy lệnh sau để tạo một controller trong module:
nest generate controller module-name
- Thay “module-name” bằng tên của module mà bạn muốn tạo controller. Nest CLI sẽ tạo ra một tệp tin controller mới trong thư mục tương ứng.
Bước 3: Định nghĩa các routes và handlers
Trong tệp tin controller mới được tạo, bạn có thể định nghĩa các routes (đường dẫn) và handlers (xử lý yêu cầu) cho API của bạn.
Ví dụ:
import { Controller, Get } from '@nestjs/common'; @Controller('api') export class ApiController { @Get('hello') getHello(): string { return 'Hello, World!'; } }
Trong ví dụ trên, chúng ta đã định nghĩa một route “/api/hello” và một handler “getHello()” để xử lý yêu cầu GET tới route đó. Handler trả về chuỗi “Hello, World!”.
Bước 4: Kết nối module và controller
Mở tệp tin module tương ứng (được tạo trong Bước 1) và import controller đã tạo:
import { Module } from '@nestjs/common'; import { ApiController } from './api.controller'; @Module({ controllers: [ApiController], }) export class ApiModule {}
Bằng cách thêm controller vào mảng “controllers” trong tệp tin module, NestJS sẽ biết cần kết nối controller này với module.
Bước 5: Đăng ký module
Mở tệp tin chính của ứng dụng (thường là “src/main.ts”) và import module đã tạo:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap();
Bằng cách truyền AppModule vào hàm NestFactory.create(), chúng ta đăng ký module và các controller của nó với ứng dụng NestJS.
Bước 6: Chạy ứng dụng
- Mở terminal hoặc command prompt và di chuyển đến thư mục dự án NestJS.
- Chạy lệnh sau để chạy ứng dụng NestJS:
npm run start
- Ứng dụng NestJS sẽ được chạy trên cổng mặc định 3000 (hoặc cổng khác nếu đã được cấu hình). Bạn có thể truy cập các API của mình thông qua các routes đã định nghĩa trong controller.
Đó là quy trình cơ bản để xây dựng API với NestJS. Từ đây, bạn có thể tiếp tục định nghĩa các routes và handlers khác, sử dụng các decorator và service để xử lý logic, và tận dụng các tính năng mạnh mẽ khác của NestJS để phát triển API đa dạng và mạnh mẽ.
Xem thêm Module DNS Node.js
Kết nối cơ sở dữ liệu trong NestJS
Để kết nối cơ sở dữ liệu trong NestJS, bạn có thể tuân theo các bước sau:
Bước 1: Cài đặt các thư viện cần thiết
- Sử dụng npm hoặc yarn để cài đặt các thư viện cần thiết cho kết nối cơ sở dữ liệu. Ví dụ, nếu bạn muốn kết nối với cơ sở dữ liệu MySQL, bạn có thể chạy lệnh:
npm install --save @nestjs/typeorm typeorm mysql
- Đảm bảo rằng bạn cài đặt đúng thư viện phù hợp với cơ sở dữ liệu mà bạn đang sử dụng (ví dụ: mysql, postgresql, mongodb, etc.).
Bước 2: Cấu hình kết nối cơ sở dữ liệu
Trong tệp tin cấu hình chính của ứng dụng (thường là “src/main.ts”), import các module cần thiết:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { TypeOrmModule } from '@nestjs/typeorm'; async function bootstrap() { const app = await NestFactory.create(AppModule); // Kết nối cơ sở dữ liệu await app.listen(3000); } bootstrap();
Để cấu hình kết nối cơ sở dữ liệu, bạn cần thêm cấu hình TypeORM vào AppModule:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConnectionOptions } from 'typeorm'; const connectionOptions: ConnectionOptions = { type: 'mysql', host: 'localhost', port: 3306, username: 'your-username', password: 'your-password', database: 'your-database', entities: [], // Thêm đường dẫn đến các entity của bạn synchronize: true, // Đồng bộ hóa cấu trúc cơ sở dữ liệu }; @Module({ imports: [TypeOrmModule.forRoot(connectionOptions)], }) export class AppModule {}
Trong ví dụ trên, chúng ta cấu hình kết nối với cơ sở dữ liệu MySQL. Bạn cần thay đổi các thông số kết nối như “host”, “port”, “username”, “password”, và “database” để phù hợp với cấu hình cơ sở dữ liệu của bạn. Bạn cũng cần thêm đường dẫn đến các entity (đối tượng) trong cơ sở dữ liệu của bạn.
Bước 3: Sử dụng kết nối cơ sở dữ liệu
Bây giờ bạn có thể sử dụng kết nối cơ sở dữ liệu trong các service hoặc controller của bạn. Ví dụ:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { User } from './user.entity'; @Injectable() export class UserService { constructor( @InjectRepository(User) private userRepository: Repository<User>, ) {} async findAll(): Promise<User[]> { return this.userRepository.find(); } }
Trong ví dụ trên, chúng ta sử dụng @InjectRepository(User)
để inject repository của entity “User” vào UserService. Bây giờ bạn có thể sử dụng các phương thức của repository để thao tác với cơ sở dữ liệu.
Đó là quy trình cơ bản để kết nối cơ sở dữ liệu trong NestJS sử dụng TypeORM. Bạn có thể tìm hiểu thêm về TypeORM và cấu hình chi tiết trong tài liệu chính thức của NestJS và TypeORM.
Xem thêm Node.js Package Manager
Testing trong NestJS
Trong NestJS, bạn có thể sử dụng các framework và thư viện phổ biến để thực hiện kiểm thử (testing) cho ứng dụng của mình. Có hai khía cạnh chính cần quan tâm khi thực hiện kiểm thử trong NestJS: unit testing (kiểm thử đơn vị) và end-to-end testing (kiểm thử từ đầu đến cuối).
Để thực hiện kiểm thử đơn vị, bạn có thể sử dụng framework như Jest hoặc Mocha cùng với các thư viện như Supertest để kiểm tra các thành phần riêng lẻ của ứng dụng như service, controller, hoặc module.
Ví dụ, để thực hiện kiểm thử đơn vị cho một service trong NestJS sử dụng Jest và Supertest, bạn có thể làm như sau:
- Cài đặt các thư viện cần thiết:
npm install --save-dev jest supertest
- Tạo một file kiểm thử (ví dụ:
user.service.spec.ts
):
import { Test } from '@nestjs/testing'; import { UserService } from './user.service'; describe('UserService', () => { let userService: UserService; beforeEach(async () => { const moduleRef = await Test.createTestingModule({ providers: [UserService], }).compile(); userService = moduleRef.get<UserService>(UserService); }); describe('findAll', () => { it('should return an array of users', async () => { const users = await userService.findAll(); expect(users).toHaveLength(2); }); }); });
Trong ví dụ trên, chúng ta tạo một test suite cho UserService trong Jest. Trước mỗi test case, chúng ta tạo một module kiểm thử và khởi tạo UserService từ module đó. Sau đó, chúng ta định nghĩa các test case, ví dụ findAll
, và sử dụng expect
để kiểm tra kết quả trả về từ hàm kiểm thử.
Để thực hiện kiểm thử từ đầu đến cuối (end-to-end testing) trong NestJS, bạn có thể sử dụng framework như Jest kết hợp với thư viện như Supertest hoặc NestJS Testing Utilities để kiểm tra hoạt động của ứng dụng từ API routes cho đến cơ sở dữ liệu.
Xem thêm Module Node.js Crypto
Ví dụ, để thực hiện kiểm thử từ đầu đến cuối cho một API route trong NestJS sử dụng Jest và Supertest, bạn có thể làm như sau:
- Cài đặt các thư viện cần thiết:
npm install --save-dev jest supertest
- Tạo một file kiểm thử (ví dụ:
app.e2e-spec.ts
):
import { Test, TestingModule } from '@nestjs/testing'; import { AppModule } from '../src/app.module'; import * as request from 'supertest'; describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/users (GET)', () => { return request(app.getHttpServer()) .get('/users') .expect(200) .expect({ message: 'Get all users' }); }); });
Trong ví dụ trên, chúng ta tạo một test suite cho AppController trong Jest. Trước mỗi test case, chúng ta khởi tạo ứng dụng NestJS và gọi hàm app.init()
để khởi động ứng dụng. Sau đó, chúng ta định nghĩa một test case để kiểm tra API route /users
sử dụng supertest
. Trong test case này, chúng ta kiểm tra mã trạng thái HTTP trả về là 200 và kiểm tra nội dung trả về từ API route.
Đây chỉ là một ví dụ đơn giản về cách thực hiện kiểm thử trong NestJS. Bạn có thể tìm hiểu thêm về Jest, Supertest, và NestJS Testing Utilities để biết thêm chi tiết và các phương pháp kiểm thử khác trong NestJS.
Xem thêm Module web trong Node.js
Ghi log và xử lý lỗi trong NestJS
Trong NestJS, bạn có thể sử dụng logger và middleware để ghi log và xử lý lỗi trong ứng dụng của mình. Dưới đây là cách thực hiện:
Ghi log trong NestJS:
- Đầu tiên, bạn cần cài đặt một thư viện ghi log. NestJS hỗ trợ nhiều thư viện ghi log phổ biến như winston, pino, bunyan, và nhiều thư viện khác. Bạn có thể chọn một thư viện ghi log phù hợp và cài đặt nó thông qua npm hoặc yarn.
- Tiếp theo, bạn cần tạo một service để quản lý việc ghi log. Ví dụ:
import { Injectable, Logger } from '@nestjs/common'; @Injectable() export class AppLogger extends Logger { // Ghi log thông qua thư viện ghi log đã chọn }
Trong ví dụ trên, chúng ta tạo một service AppLogger
kế thừa từ lớp Logger
của NestJS. Bạn có thể tuỳ chỉnh AppLogger
để sử dụng thư viện ghi log mà bạn đã cài đặt.
- Bây giờ, bạn có thể sử dụng
AppLogger
trong các module, service hoặc controller khác trong ứng dụng của bạn để ghi log. Ví dụ:
import { Injectable } from '@nestjs/common'; import { AppLogger } from './app.logger'; @Injectable() export class UserService { constructor(private readonly logger: AppLogger) {} createUser(user: any) { this.logger.log(`Creating user: ${user.name}`); // ... } }
Trong ví dụ trên, chúng ta sử dụng AppLogger
để ghi log khi tạo người dùng trong UserService
.
Xử lý lỗi trong NestJS:
- NestJS cung cấp một cách tiếp cận xử lý lỗi thông qua middleware. Bạn có thể tạo một middleware tùy chỉnh để xử lý các loại lỗi trong ứng dụng của mình.
- Để tạo một middleware xử lý lỗi, bạn cần tạo một class middleware và triển khai interface
ExceptionFilter
. Ví dụ:
import { Catch, ExceptionFilter, ArgumentsHost } from '@nestjs/common'; import { Response, Request } from 'express'; @Catch() export class ErrorHandlingFilter implements ExceptionFilter { catch(exception: any, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); // Xử lý và gửi phản hồi lỗi response.status(500).json({ statusCode: 500, timestamp: new Date().toISOString(), message: 'Internal Server Error', }); } }
Trong ví dụ trên, chúng ta triển khai ExceptionFilter
và sử dụng catch
method để xử lý và gửi phản hồi lỗi.
- Để sử dụng middleware xử lý lỗi, bạn có thể áp dụng nó cho một module hoặc controller cụ thể trong ứng dụng của bạn. Ví dụ:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'; import { ErrorHandlingFilter } from './error-handling.filter'; @Module({ // ... }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer.apply(ErrorHandlingFilter).forRoutes('*'); } }
Trong ví dụ trên, chúng ta áp dụng ErrorHandlingFilter
cho tất cả các routes trong ứng dụng.
Đó là cách bạn có thể ghi log và xử lý lỗi trong NestJS. Bạn có thể tùy chỉnh và mở rộng các phương pháp này tùy theo yêu cầu của ứng dụng của mình.
Xem thêm AngularJS Modules – Hướng dẫn sử dụng Modules trong AngularJS