Latest Post

Tăng thứ hạng và truy cập tự nhiên với 10 phương pháp SEO hay nhất Kiếm Tiền Online (mmo): Khái Niệm và Các Hình Thức Phổ Biến

Khác với PHP, hầu hết các framework Node.js không giới hạn về cấu trúc thư mục cố định. Điều này mang lại sự linh hoạt cho việc tùy chỉnh cấu trúc dựa trên nhu cầu và sở thích cá nhân. Tuy nhiên, đối với người mới, điều này có thể là một thách thức. Xây dựng một dự án với cấu trúc hợp lý là quan trọng để chuẩn bị cho một dự án linh hoạt, hiệu quả, dễ mở rộng và bảo trì. Mặc dù bạn có thể xây dựng một dự án theo bất kỳ cách nào, miễn là nó chạy được; nhưng vấn đề sẽ trở nên phức tạp khi ứng dụng lớn lên và cần mở rộng. Trong bài này, chúng ta sẽ tìm hiểu về một số nguyên tắc cơ bản để xây dựng cấu trúc cho một dự án Node.js.

Có nhiều cách để tổ chức mã nguồn cho một dự án Node.js, mỗi cách đều có những ưu và nhược điểm riêng. Dựa trên kinh nghiệm và chia sẻ từ cộng đồng phát triển Node.js, phần lớn các cách tổ chức mã nguồn đều hướng đến hai yếu tố chính: mã sạch và khả năng mở rộng tính năng. Dựa trên những yếu tố này, chúng ta có thể xem xét năm nguyên tắc sau:

1. Tổ chức thư mục source code dựa trên tính năng

Giả sử rằng bạn đang làm việc với một project có các tính năng liên quan đến user và poroduct. Với mỗi tính năng đó ta sẽ cần có controller, model và view. Khi đó ta có thể sử dụng một cấu trúc thư mục như thế này

.
├── controllers
|   ├── product.js
|   └── user.js
├── models
|   ├── product.js
|   └── user.js
├── views
|   ├── product.hbs
|   └── user.hbs

Vấn đề của cách triển khai này như sau:

  • Mỗi file cần thiết với một tính năng (user hoặc product) bị phân tán đến một thư mục riêng biệt (độc lập nhau: controllers, models, views). Do đó để có thể hiểu được mỗi tính năng hoạt động thế nào, ta buộc phải duyệt cả cây thư mục để xem chi tiết vào từng phần (1)
  • Thường thì với mỗi tính năng, controller sẽ cần và thường xuyên làm việc với model và view của tính năng đó. Ở cách sắp xếp trên thì controllers/product.js sẽ cần làm việc với models/product.js; khi đó tại controller product ta sẽ phải require model như sau: let ProductModel = require('../models/product');
  • Một vấn đề nữa đó là ngay trong quá trình development, bạn sẽ thường làm việc với controller, model và view gần như liên tục và cùng nhau, việc phải di chuyển cây thư mục quá dài giữa các thành phần này cũng sẽ mất thêm thời gian

“Rule 1: Organize your files around features, not roles!” via @risingstack

Thay vì sử dụng cấu trúc như trên, chúng ta có thể sử dụng cấu trúc dưới đây, trong đó sẽ lấy tính năng (product, user) làm cách để phân chia thư mục. Cách này sẽ giúp chúng ta hiểu được các tính năng một cách đơn giản hơn

.
├── product
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   └── view.hbs
├── user
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   └── view.hbs

2. Không nên đặt logic trong file index

Trong Node.js, khi sử dụng lệnh require để đưa vào một thư mục, hệ thống require trước hết sẽ tìm kiếm tệp package.json để xác định tệp mục tiêu cần được require. Nếu package.json không tồn tại, hệ thống require sẽ tự động sử dụng tệp index.js làm tệp chính. Điều này có nghĩa là index.js thường được sử dụng như một điểm vào để require một thư mục, thay vì sử dụng cú pháp require('./product/index.js'), ta có thể viết ngắn gọn hơn với require('./product').

Trong quá trình phát triển, có những lúc chúng ta muốn hoặc phải điều chỉnh cách một tính năng hoạt động, thay đổi các tài nguyên mà tính năng đó yêu cầu. Nếu tệp index.js chứa quá nhiều logic, việc thay đổi có thể trở nên phức tạp và gặp nhiều rủi ro. Vì lý do này, tốt nhất là tránh đặt các đoạn mã logic quan trọng trong index.js. Thay vào đó, index.js nên chỉ được sử dụng như một tệp khởi tạo, cung cấp tài nguyên từ các module (tệp) khác đã được xuất.

3. Đặt file test ngay cạnh file thực thi

Test không chỉ đơn giản là công đoạn để kiểm tra xem một module có thể sản sinh ra kết quả đúng như mong đợi hay không, mà còn đóng vai trò như một tài liệu cho module đó. Việc sử dụng các tệp kiểm thử không chỉ giúp xác nhận tính đúng đắn của API mà còn mang lại lợi ích lớn trong việc hiểu cách sử dụng, các tham số, và kết quả của module.

Bằng cách đặt tệp kiểm thử ngay cạnh module chính, chúng ta tạo ra một cơ hội thuận lợi để kiểm tra lại API một cách thuận tiện. Điều này không chỉ làm cho quá trình kiểm thử trở nên dễ dàng mà còn giúp tăng tính minh bạch trong quá trình phát triển và bảo trì mã nguồn.

“Rule 3: Place your test files next to the implementation.” via @risingstack

.
├── product
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs
├── user
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs

4. Sử dụng thư mục config

Một điểm rất thuận tiện trong Laravel đó là gần như tất cả các config cho các package hoặc feature đều có thể được override và lưu trữ tập trung tại một chỗ (thư mục config). Cách làm này sẽ giúp chúng ta dễ tìm kiếm và thao tác khi setup hay điều chỉnh những thông tin cần thiết trong quá trình deployment

.
├── config
|   ├── server.js
|   ├── storage.js
|   ├── db.js
├── product
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs
├── user
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs

5. Đặt các npm script dài trong thư mục scripts thay vì viết vào file package.json

Khi bạn làm việc với các đoạn mã dài, việc viết trực tiếp vào tệp package.json không phải lúc nào cũng là lựa chọn tối ưu. Thậm chí, điều này có thể gây khó khăn trong việc đọc và mở rộng mã nguồn. NPM mang lại sự linh hoạt trong việc thực thi script, không chỉ giới hạn ở việc chạy các script đã được đặt tên trong tệp package.json, mà còn cho phép chúng ta chạy trực tiếp các tệp thực thi.

npm run --prefix /path/to/file

.
├── scripts
|   ├── setup.sh
|   ├── build.sh
|   ├── clean.sh
├── config
|   ├── server.js
|   ├── storage.js
|   ├── db.js
├── product
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs
├── user
|   ├── index.js
|   ├── controller.js
|   ├── model.js
|   ├── test.js
|   └── view.hbs

Trên đây là một số quy tắc đơn giản giúp chúng ta có thể start một project một cách hợp lý và dễ dàng hơn. Một số thông tin mở rộng có thểm tham khảo tại: https://github.com/RisingStack/multi-process-nodejs-example

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *