0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Cấu Trúc Thư Mục Đề Xuất Cho Node.js và TypeScript 2025

Đăng vào 7 tháng trước

• 12 phút đọc

Cấu Trúc Thư Mục Đề Xuất Cho Node.js (TypeScript) 2025

Giới Thiệu

Cấu trúc thư mục là một yếu tố quan trọng trong việc phát triển ứng dụng Node.js, đặc biệt là khi sử dụng TypeScript. Việc tổ chức mã nguồn một cách hợp lý không chỉ giúp cải thiện khả năng bảo trì và mở rộng ứng dụng mà còn tạo điều kiện thuận lợi cho việc làm việc nhóm. Trong bài viết này, chúng ta sẽ khám phá các nguyên tắc cơ bản, cấu trúc thư mục đề xuất và những thực tiễn tốt nhất để tối ưu hóa ứng dụng Node.js của bạn.

Nguyên Tắc Chính Của Cấu Trúc Node.js Hiện Đại 🏗️

Mục tiêu là vượt qua một tệp app.js đơn giản và tổ chức mã nguồn thành các thành phần logic, có thể tái sử dụng. Điều này giúp:

  • Khả năng mở rộng: Ứng dụng có thể phát triển mà không trở nên lộn xộn.
  • Dễ bảo trì: Dễ dàng tìm thấy, gỡ lỗi và cập nhật các phần cụ thể của mã.
  • Kiểm thử: Các đơn vị mã riêng lẻ có thể được kiểm thử độc lập.
  • Cộng tác nhóm: Nhiều lập trình viên có thể làm việc trên các phần khác nhau của ứng dụng mà không xung đột.

Cấu Trúc Đề Xuất Dựa Trên Tính Năng

Sử dụng cấu trúc dựa trên tính năng là một phương pháp hiện đại và tuyệt vời để tổ chức ứng dụng Node.js Express, đặc biệt là cho các dự án lớn. Phương pháp này nhóm các tệp liên quan (bộ điều khiển, dịch vụ, mô hình) theo miền hoặc tính năng thay vì theo loại. Điều này giúp mã nguồn trở nên dễ mở rộng, dễ dàng điều hướng và tốt hơn cho việc cộng tác nhóm.

Cấu Trúc Thư Mục Đề Xuất

Copy
pramodboda-app/
├── src/
│   ├── features/
│   │   ├── auth/            # Tất cả các tệp liên quan đến xác thực người dùng
│   │   │   ├── auth.controller.ts   # Xử lý yêu cầu: xử lý đầu vào và gọi dịch vụ 'auth'
│   │   │   ├── auth.model.ts        # Lược đồ cơ sở dữ liệu và mô hình dữ liệu liên quan đến 'auth'
│   │   │   ├── auth.route.ts        # Định nghĩa các điểm cuối API của 'auth' và ánh xạ chúng tới các bộ điều khiển
│   │   │   └── auth.service.ts      # Logic kinh doanh cốt lõi; "bộ não" của tính năng 'auth'
│   │   │
│   │   ├── users/           # Tất cả các tệp liên quan đến quản lý người dùng
│   │   │   ├── user.controller.ts   # Xử lý yêu cầu: xử lý đầu vào và gọi dịch vụ 'users'
│   │   │   ├── user.model.ts        # Lược đồ cơ sở dữ liệu và mô hình dữ liệu liên quan đến 'users'
│   │   │   ├── user.route.ts        # Định nghĩa các điểm cuối API của 'users' và ánh xạ chúng tới các bộ điều khiển
│   │   │   └── user.service.ts      # Logic kinh doanh cốt lõi; "bộ não" của tính năng 'users'
│   │   │
│   │   └── products/        # Tất cả các tệp liên quan đến sản phẩm
│   │       ├── product.controller.ts  # Xử lý yêu cầu: xử lý đầu vào và gọi dịch vụ 'product'
│   │       ├── product.model.ts       # Lược đồ cơ sở dữ liệu và mô hình dữ liệu liên quan đến 'products'
│   │       ├── product.route.ts       # Định nghĩa các điểm cuối API của 'products' và ánh xạ chúng tới các bộ điều khiển
│   │       └── product.service.ts     # Logic kinh doanh cốt lõi; "bộ não" của tính năng 'products'
│   │
|   ├── api/                # Các điểm vào API (ví dụ: v1/)
│   ├── config/             # Tệp cấu hình tập trung (DB, xác thực, v.v.)
│   ├── middleware/         # Middleware Express tùy chỉnh (xác thực, ghi nhật ký, v.v.)
│   ├── utils/              # Các hàm trợ giúp chung và mã tái sử dụng
│   │
│   └── index.ts            # Điểm vào chính cho logic ứng dụng
|
├── tests/                  # Tất cả các bài kiểm tra đơn vị và tích hợp
├── .env                    # Tất cả biến môi trường cho ứng dụng
├── .gitignore              # Tệp này bao gồm những gì là tất cả các tệp/thư mục không nên đưa vào kho Git của bạn
├── package.json
├── server.ts               # Thiết lập và khởi động máy chủ
└── tsconfig.json

Tại Sao Điều Này Là Một Ý Tưởng Tốt?

  • Tính gắn kết: Tất cả mã cho một tính năng cụ thể (ví dụ: người dùng) được đặt ở một nơi, giúp dễ dàng hiểu và làm việc trên tính năng đó một cách độc lập.
  • Khả năng mở rộng: Khi ứng dụng của bạn phát triển, bạn chỉ cần thêm các thư mục mới cho các tính năng mới mà không làm rối một thư mục controllers/ hay services/ trung tâm.
  • Dễ bảo trì: Bạn có thể xóa toàn bộ thư mục tính năng khi không còn cần thiết mà không ảnh hưởng đến phần còn lại của ứng dụng.

Phân Tích Các Thư Mục Chính

Cấu trúc thư mục này sử dụng tổ chức dựa trên tính năng, nhóm tất cả mã liên quan cho một miền cụ thể lại với nhau. Cách tiếp cận này rất có thể mở rộng và duy trì sự phân tách rõ ràng về các mối quan tâm. Dưới đây là phân tích các thư mục và tệp chính trong cấu trúc đã cung cấp:

Thư Mục src/

Đây là thư mục chính cho mã nguồn của ứng dụng của bạn. Giữ tất cả các tệp nguồn ở đây giúp giữ cho thư mục gốc của dự án sạch sẽ.

  • features/: Đây là cốt lõi của thiết kế mô-đun ứng dụng của bạn. Mỗi thư mục con ở đây đại diện cho một miền hoặc "tính năng" riêng biệt của ứng dụng, như auth hoặc users. Cách tiếp cận này, được gọi là Thiết kế theo miền (Domain-Driven Design - DDD), đảm bảo rằng tất cả các thành phần liên quan đến một chức năng kinh doanh cụ thể được đặt cùng nhau.
    • auth/, users/, products/: Những thư mục này là các tính năng của bạn. Mỗi thư mục chứa các tệp controller, model, route, và service cụ thể cho tính năng đó. Điều này ngăn mã của bạn trở thành một mớ hỗn độn khi nó phát triển. Ví dụ, tất cả mã để quản lý người dùng nằm trong features/users/.
      • auth.controller.ts: Xử lý các yêu cầu liên quan đến xác thực. Nó nhận yêu cầu, xác thực đầu vào và gọi auth.service.ts để thực hiện logic kinh doanh, sau đó gửi phản hồi về phía khách hàng.
      • auth.model.ts: Định nghĩa cấu trúc dữ liệu của bạn trong cơ sở dữ liệu cho tính năng xác thực (ví dụ, lược đồ người dùng trong Mongoose).
      • auth.route.ts: Định nghĩa các điểm cuối API cho xác thực (ví dụ, /api/auth/login, /api/auth/register) và ánh xạ chúng đến các hàm của bộ điều khiển thích hợp.
      • auth.service.ts: Chứa logic kinh doanh cho tính năng. Đây là "bộ não" của tính năng của bạn, nơi các thao tác phức tạp như băm mật khẩu, tạo token JWT và tương tác với cơ sở dữ liệu diễn ra. Bộ điều khiển chỉ đơn giản là điều phối các cuộc gọi dịch vụ.
  • api/: Một thực tiễn phổ biến để phiên bản hóa API của bạn (ví dụ: v1/). Bạn có thể di chuyển các tệp route của mình vào src/api/v1/ để hỗ trợ nhiều phiên bản API trong tương lai.
  • config/: Chứa tất cả các tệp cấu hình cho ứng dụng của bạn, chẳng hạn như cài đặt kết nối cơ sở dữ liệu, khóa API, hoặc các biến cụ thể cho từng môi trường.
  • middleware/: Chứa tất cả các hàm middleware Express tùy chỉnh của bạn, có thể được chia sẻ giữa nhiều tính năng. Ví dụ bao gồm kiểm tra xác thực, xử lý lỗi, và ghi nhật ký yêu cầu.
  • utils/: Một kho lưu trữ cho các hàm trợ giúp tái sử dụng không thuộc về bất kỳ tính năng hoặc lớp nào cụ thể. Các ví dụ bao gồm các hàm kiểm tra, chức năng gửi email, hoặc các hàm tiện ích chung.
  • index.ts: Tệp trung tâm thiết lập ứng dụng Express của bạn. Nó nhập và áp dụng tất cả các middleware toàn cục (như express.json()cors) và đăng ký tất cả các route tính năng của bạn. Tệp này hoạt động như một trung tâm cho logic ứng dụng của bạn, nhưng không khởi động máy chủ.

Tệp & Thư Mục Cấp Rễ

  • tests/: Một thư mục dành riêng cho tất cả các bài kiểm tra đơn vị và tích hợp của bạn. Tổ chức chúng ở đây giữ chúng tách biệt khỏi mã sản xuất của bạn.
  • .env: Lưu trữ các biến cụ thể cho từng môi trường. Tệp này không bao giờ nên được đưa vào quản lý phiên bản.
  • .gitignore: Chỉ định các tệp và thư mục mà Git nên bỏ qua, chẳng hạn như node_modules.env.
  • server.ts: Điểm vào cho ứng dụng của bạn. Trách nhiệm duy nhất của nó là nhập ứng dụng Express từ index.ts và khởi động máy chủ, lắng nghe trên một cổng cụ thể. Sự tách biệt này làm cho tệp index.ts của bạn rất dễ kiểm thử, vì bạn có thể nhập phiên bản ứng dụng mà không cần khởi động máy chủ.
  • tsconfig.json: Tệp cấu hình cho trình biên dịch TypeScript, định nghĩa cách mã TypeScript của bạn nên được biên dịch thành JavaScript.
  • package.json: Quản lý siêu dữ liệu và các phụ thuộc của dự án của bạn.

Tại Sao Nên Tách Biệt server.tsindex.ts?

Việc tách biệt cài đặt ứng dụng Express khỏi phần lắng nghe máy chủ là một thực tiễn phổ biến và tốt. Điều này làm cho ứng dụng của bạn dễ kiểm thử hơn, vì bạn có thể nhập phiên bản ứng dụng Express trực tiếp vào các tệp kiểm thử của mình mà không cần phải khởi động một máy chủ.

Ví Dụ Chi Tiết

src/server.ts

typescript Copy
// src/server.ts
import { app } from './index';
import { connectDB } from './config/database'; // Giả sử bạn có cấu hình DB

const PORT = process.env.PORT || 5000;

// Kết nối đến cơ sở dữ liệu trước khi khởi động máy chủ
connectDB();

app.listen(PORT, () => {
    console.log(`Máy chủ đang chạy trên cổng ${PORT}`);
});

src/index.ts

typescript Copy
// src/index.ts
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import compression from 'compression';

import authRoutes from './features/auth/auth.route';
import userRoutes from './features/users/user.route';
// Nhập các route tính năng khác ở đây

export const app = express();

// Middleware Toàn Cục
app.use(express.json());       // Phân tích thân JSON
app.use(express.urlencoded({ extended: true })); // Phân tích các thân mã hóa URL
app.use(cors());               // Bật chia sẻ tài nguyên giữa các nguồn
app.use(helmet());             // Bảo mật tiêu đề HTTP
app.use(compression());        // Nén các thân phản hồi

// Các Route API
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
// Sử dụng các route tính năng khác ở đây

Cấu Trúc Dựa Trên Lớp Dịch Vụ

Nếu bạn thích cấu trúc dựa trên lớp dịch vụ, hãy tham khảo cấu trúc dưới đây:

Cấu Trúc Dựa Trên Lớp Dịch Vụ

Cấu trúc này tách biệt mã theo mục đích và miền, thường kết hợp các yếu tố của mô hình MVC với cách tiếp cận lớp dịch vụ.

Copy
my-web-app/
├── src/
│   ├── api/             # Các điểm vào API (ví dụ: v1/)
│   ├── config/          # Tệp cấu hình tập trung (DB, xác thực, v.v.)
│   ├── controllers/     # Xử lý yêu cầu: xử lý đầu vào và gọi dịch vụ
│   ├── middleware/      # Middleware Express tùy chỉnh (xác thực, ghi nhật ký, v.v.)
│   ├── models/          # Lược đồ cơ sở dữ liệu và mô hình dữ liệu
│   ├── routes/          # Định nghĩa các điểm cuối API và ánh xạ chúng tới các bộ điều khiển
│   ├── services/        # Logic kinh doanh cốt lõi; "bộ não" của ứng dụng
│   └── utils/           # Các hàm trợ giúp chung và mã tái sử dụng
│
├── public/              # Tệp tĩnh (CSS, JS, hình ảnh)
├── tests/               # Tất cả các bài kiểm tra đơn vị và tích hợp
├── .env                 # Biến môi trường cho phát triển cục bộ
├── .gitignore
├── package.json
├── server.js            # Điểm vào ứng dụng chính
└── README.md

Kết Luận

Cấu trúc thư mục là một yếu tố thiết yếu trong việc phát triển ứng dụng Node.js. Bằng cách áp dụng phương pháp tổ chức hợp lý, bạn không chỉ cải thiện khả năng bảo trì và mở rộng ứng dụng mà còn tăng cường khả năng làm việc nhóm. Hãy thử nghiệm với các cấu trúc khác nhau và chọn cấu trúc phù hợp nhất với dự án của bạn. Nếu bạn có bất kỳ câu hỏi nào, hãy để lại ý kiến bên dưới! Theo dõi tôi để cập nhật những xu hướng công nghệ mới nhất nhé! 👇

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào