TypeScript, Node.js & Express: Xây dựng nền tảng dự án (P1)

Anh em đã nghe về TypeScript và đang tò mò liệu nó có thể làm gì cho dự án Express của mình? Đừng lo, mình sẽ hướng dẫn cho anh em chi tiết từng bước một! Bài viết này sẽ giúp anh em hiểu tại sao TypeScript lại “hot” đến vậy và cách kết hợp nó với Node.js và Express một cách dễ dàng nhất. Bắt đầu thôi nào!
Tại sao nên dùng TypeScript với Node.js và Express?
TypeScript đang ngày càng được ưa chuộng khi làm việc với Node.js và Express, và lý do thì nhiều vô kể! Nếu bạn đang quản lý một ứng dụng phức tạp hoặc làm việc trong team đông người, TypeScript chính là “vị cứu tinh” của bạn đấy!
Những lợi ích không thể bỏ qua của TypeScript:
- Code chắc chắn hơn nhờ hệ thống kiểu dữ liệu tĩnh (static typing)
- Teamwork dễ dàng hơn và dự án dễ mở rộng
- IDE hỗ trợ mạnh mẽ, gợi ý thông minh
- Tương thích với các thư viện JavaScript
Với TypeScript, code của anh em sẽ mạnh mẽ và rõ ràng hơn rất nhiều nhờ khả năng kiểm tra kiểu dữ liệu ngay từ khi code, giúp giảm thiểu những lỗi “củ chuối” mà chúng ta thường gặp khi chạy ứng dụng. Hơn nữa, khi làm việc nhóm, TypeScript giúp mọi người hiểu code của nhau dễ dàng hơn, đồng thời cũng giúp dự án dễ dàng mở rộng và bảo trì về sau.
Anh em cứ tưởng tượng xem, IDE của anh em sẽ thông minh hơn hẳn khi hỗ trợ autocompletion và báo lỗi ngay tức thì, giúp tăng năng suất code lên đáng kể. Đặc biệt, dù dự án lớn hay nhỏ, TypeScript đều có thể “cân” được hết, mang lại sự linh hoạt và ổn định cho mọi ứng dụng.
Express TypeScript là gì?
“Express TypeScript” đơn giản là việc sử dụng framework Express trong một dự án TypeScript. Anh em sẽ viết code server Express bằng TypeScript, tận dụng các định nghĩa kiểu (thường là thông qua @types/express
) để kiểm tra kiểu dữ liệu, tự động hoàn thành code và tài liệu hóa tốt hơn.
Nói đơn giản hơn, đây là sự kết hợp giữa sự linh hoạt của Express với những lợi thế về an toàn và công cụ phát triển mà TypeScript mang lại.
Và bây giờ, hãy bắt tay vào xây dựng một dự án Express Typescript để xem thử chúng ta làm được gì với nó nhé. Bài viết sẽ khá dài vì mình sẽ tiếp cận theo từng bước, đặc biệt là trong phần cấu hình nên mình sẽ chia làm các phần nhỏ nhé. Let’s go!
Cấu trúc dự án
Chuẩn bị môi trường để bắt đầu
Trước khi lao vào code, hãy đảm bảo anh em có đủ những thứ sau:
- Node.js phiên bản từ 18.x trở lên
- Một package manager như npm, pnpm hoặc Yarn
- Hiểu biết cơ bản về Node.js và Express
Đừng lo nếu vẫn chưa thành thạo lắm, Siucode sẽ cùng anh em đi từng bước một!
Khởi tạo dự án
Để bắt đầu hành trình “type-safe” này, chúng ta cần khởi tạo một project Node.js mới. Anh em mở terminal lên và “chạy” lệnh sau tại thư mục mà anh em muốn tạo project (ở đây mình đặt là ts-node-express
luôn):
mkdir ts-node-express
cd ts-node-express
npm init -y
Lệnh npm init -y
sẽ tạo ra một file package.json
với các thông tin cơ bản về project của anh em. File này giống như “giấy khai sinh” của project, nơi lưu trữ tên project, phiên bản, các script để chạy và quản lý các thư viện mà project sử dụng.
Tiếp theo, cài đặt các thư viện cần thiết:
npm install express dotenv
Express là một framework web rất phổ biến và mạnh mẽ cho Node.js, giúp anh em xây dựng các ứng dụng web và API một cách nhanh chóng. Còn dotenv sẽ giúp anh em quản lý các biến môi trường (environment variables) một cách an toàn và tiện lợi, thường được dùng để cấu hình các thông tin nhạy cảm như API keys hay connection string.
Tiếp theo, chúng ta sẽ cài đặt các thư viện khác cho quá trình phát triển, những thư viện này sẽ giúp anh em code hiệu quả và mượt mà hơn. Chúng ta sẽ cài đặt chúng dưới dạng devDependencies
vì chúng chỉ cần thiết trong quá trình phát triển, không cần thiết khi ứng dụng đã được deploy:
npm install -D typescript ts-node @types/node @types/express nodemon eslint prettier
Hãy cùng điểm qua vai trò của từng thư viện này:
ts-node
: Đây là một công cụ giúp anh em có thể “quẩy” trực tiếp các file TypeScript mà không cần phải biên dịch ra JavaScript trước, rất hữu ích trong quá trình phát triển.@types/node
: Thư viện này cung cấp các định nghĩa kiểu (type definitions) cho các module core của Node.js. Nhờ đó, TypeScript sẽ hiểu rõ hơn về các hàm và đối tượng mà Node.js cung cấp, giúp việc code trở nên an toàn hơn.@types/express
: Tương tự như@types/node
, thư viện này cung cấp các định nghĩa kiểu cho framework Express. Khi sử dụng Express với TypeScript, anh em sẽ nhận được sự hỗ trợ tốt nhất từ IDE, ví dụ như gợi ý code và kiểm tra lỗi.nodemon
: Đây là một công cụ rất quen thuộc với dân dev Node.js. Nó sẽ tự động restart server của anh em mỗi khi có bất kỳ thay đổi nào trong code, giúp tiết kiệm thời gian và công sức.eslint
: Công cụ này sẽ giúp anh em “soi lỗi” và “gò” code theo một chuẩn nhất định. Nó giúp đảm bảo code của anh em sạch sẽ, dễ đọc và tuân theo các quy tắc coding style.prettier
: Prettier sẽ giúp anh em “format” code một cách tự động theo một style đã được cấu hình. Điều này giúp code của toàn bộ team trở nên đẹp và đồng nhất, tránh những tranh cãi về formatting không đáng có.
Sau khi cài đặt xong, anh em mở file package.json
ra sẽ thấy các dependencies vừa cài đặt được liệt kê trong phần dependencies
và devDependencies
.
"dependencies": {
"dotenv": "^16.4.7",
"express": "^5.1.0"
},
"devDependencies": {
"@types/express": "^5.0.1",
"@types/node": "^22.14.0",
"eslint": "^9.23.0",
"nodemon": "^3.1.9",
"prettier": "^3.5.3",
"ts-node": "^10.9.2",
"typescript": "^5.8.2"
}
Cấu hình TypeScript: File tsconfig.json
Để TypeScript có thể hiểu và biên dịch code của anh em một cách chính xác, chúng ta cần cấu hình nó thông qua file tsconfig.json
. Anh em “chạy lệnh” sau trong terminal để tạo file này ở thư mục gốc của project:
npx tsc --init
Lệnh này sẽ tạo ra một file tsconfig.json
với rất nhiều option cấu hình. Anh em có thể tham khảo một cấu hình thường được sử dụng như sau:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
Hãy cùng xem qua một vài option quan trọng trong cấu hình này:
target
: Option này chỉ định phiên bản ECMAScript mà TypeScript sẽ “biên dịch” sang. Trong ví dụ này, chúng ta đang chọnES2020
, một phiên bản hiện đại và được hỗ trợ tốt bởi Node.js.module
: Option này xác định kiểu module code mà TypeScript sẽ tạo ra.commonjs
là một lựa chọn phổ biến cho các project Node.js.outDir
: Đây là thư mục mà các file JavaScript sau khi “biên dịch” sẽ được đặt vào. Chúng ta thường đặt nó là./dist
.rootDir
: Option này chỉ định thư mục chứa các file TypeScript gốc của project. Chúng ta sẽ tổ chức code TypeScript trong thư mục./src
.strict
: Khi option này được “bật” làtrue
, TypeScript sẽ thực hiện kiểm tra type một cách nghiêm ngặt hơn, giúp phát hiện ra nhiều lỗi tiềm ẩn trong code.esModuleInterop
: Option này giúp TypeScript “tương tác” tốt hơn với các module CommonJS (kiểu module phổ biến trong Node.js) khi import chúng vào code TypeScript.skipLibCheck
: Option này cho phép bỏ qua việc kiểm tra type của các file khai báo (.d.ts
). Đôi khi, các thư viện bên thứ ba có thể có các file khai báo không hoàn hảo, và việc bỏ qua kiểm tra có thể giúp quá trình build diễn ra suôn sẻ hơn.forceConsistentCasingInFileNames
: Option này “bắt buộc” anh em phải viết hoa/thường nhất quán cho tên file khi import. Điều này giúp tránh những lỗi khó hiểu có thể xảy ra trên các hệ điều hành khác nhau.include
: Mảng này chỉ định các file và thư mục nào cần được TypeScript “biên dịch”. Ở đây, chúng ta đang chỉ định tất cả các file và thư mục bên trong thư mụcsrc
.exclude
: Mảng này chỉ định các file và thư mục nào cần được TypeScript “bỏ qua” trong quá trình biên dịch. Thư mụcnode_modules
thường được loại trừ vì nó chứa các thư viện đã được biên dịch.
Cấu trúc thư mục
Một cấu trúc thư mục gọn gàng sẽ giúp project của anh em dễ quản lý và bảo trì hơn. Dưới đây là một cấu trúc thư mục thường được sử dụng cho các project Node.js và Express với TypeScript :
├── dist/
├── src/
│ ├── config/
│ │ └── config.ts
│ ├── controllers/
│ │ └── itemController.ts
│ ├── middlewares/
│ │ └── errorHandler.ts
│ ├── models/
│ │ └── item.ts
│ ├── routes/
│ │ └── itemRoutes.ts
│ ├── app.ts
│ └── server.ts
├──.env
├── package.json
├── tsconfig.json
├──.eslintrc.js
└──.prettierrc
Hãy cùng xem qua vai trò của từng thư mục và file:
dist/
: Thư mục này sẽ chứa các file JavaScript đã được biên dịch từ code TypeScript trong thư mụcsrc/
.src/
: Đây là thư mục chính chứa toàn bộ code TypeScript của project.config/
: Thư mục này thường chứa các file cấu hình, ví dụ như file để “load” và “type” các biến môi trường từ file.env
.controllers/
: Thư mục này chứa các controller, nơi xử lý logic nghiệp vụ của ứng dụng. Ví dụ,itemController.ts
có thể chứa logic CRUD (Create, Read, Update, Delete) cho các “items”.middlewares/
: Thư mục này chứa các middleware, ví dụ nhưerrorHandler.ts
để “xử lý” các lỗi toàn cục trong ứng dụng.models/
: Thư mục này chứa các model, nơi định nghĩa cấu trúc dữ liệu (types hoặc interfaces) và có thể chứa logic tương tác với database. Ví dụ,item.ts
có thể định nghĩa type cho một “item” và có thể chứa “nơi chứa” dữ liệu tạm thời cho mục đích demo.routes/
: Thư mục này chứa các file định nghĩa các route API của ứng dụng. Ví dụ,itemRoutes.ts
sẽ định nghĩa các route cho việc quản lý “items”.app.ts
: File này thường là nơi “lắp ráp” toàn bộ ứng dụng Express, bao gồm việc cấu hình các middleware và mount các routes.server.ts
: File này là điểm vào chính của ứng dụng, nơi “khởi chạy” server Express và lắng nghe các request từ client.
.env
: File này dùng để chứa các biến môi trường của ứng dụng, ví dụ như port, database connection string, API keys, v.v.package.json
: File này chứa thông tin về project, các dependencies và các script để chạy ứng dụng.tsconfig.json
: File cấu hình TypeScript mà chúng ta đã tạo ở bước trước..eslintrc.js
: File cấu hình ESLint để kiểm tra code style..prettierrc
: File cấu hình Prettier để format code.
Tạm kết
Vậy là chúng ta đã hoàn thành xong cơ bản cấu trúc cơ bản của dự án trong phần đầu tiên này. Hy vọng những thông tin trên đã giúp anh em có cái nhìn rõ ràng hơn về dự án. Còn rất nhiều điều thú vị mình muốn chia sẻ với anh em trong phần tiếp theo. Hẹn gặp lại anh em ở phần 2: Tạo API với TypeScript, Node.js và Express. Đừng quên để lại comment chia sẻ cảm nghĩ của anh em về phần 1 nhé!