Bỏ qua điều hướng

Express.js là gì? Web framework tối giản cho Node.js

Express.js là framework tối giản cho Node.js, dùng định tuyến và middleware để dựng ứng dụng web và API. Kèm những thay đổi lớn của Express 5 so với bản 4.

Tuan Tran Van
10 phút đọc
Mục lục (9 phần)
  1. Express.js là gì?
  2. Một ứng dụng Express tối thiểu trông như thế nào?
  3. Middleware: cơ chế cốt lõi của Express
  4. Định tuyến và express.Router
  5. Xử lý lỗi trong Express
  6. Express 5 khác Express 4 ở đâu?
  7. Express có còn được duy trì tốt không?
  8. Khi nào nên chọn Express — và khi nào không?
  9. Tài liệu tham khảo

Express.js là một web framework tối giản, linh hoạt và không áp đặt (unopinionated) chạy trên Node.js. Nó phủ một lớp mỏng lên môi trường chạy (runtime), đủ để bạn dựng ứng dụng web và API mà không che lấp các tính năng cốt lõi của Node.js.

Thay vì áp một bộ quy tắc cứng nhắc, Express chỉ lo phần thiết yếu: xử lý HTTP request và middleware. Phần còn lại là việc của bạn: tổ chức thư mục ra sao, lắp thêm thư viện nào từ npm.

Express.js là lớp framework mỏng, tối giản phủ trên môi trường chạy Node.js

Express.js là gì?

Express.js là một lớp mỏng nằm trên Node.js. Nó không tái định nghĩa cách Node.js hoạt động. Nó chỉ dọn giúp bạn mấy việc lặp đi lặp lại: định tuyến, đọc dữ liệu gửi lên, dựng phản hồi trả về. Framework này đứng trên bốn trụ cột: ứng dụng web (đơn trang hoặc đa trang), API (các dịch vụ RESTful), hiệu năng (giữ nguyên tốc độ của Node.js) và hệ thống middleware.

Bốn trụ cột của Express.js đặt trên môi trường chạy Node.js: ứng dụng web, API, hiệu năng và middleware

Nhưng thứ đáng nói nhất lại nằm ở chữ "unopinionated", tức không áp đặt. Express không bắt bạn dùng một cấu trúc thư mục cụ thể, cũng không chọn sẵn ORM hay template engine nào. Con dao hai lưỡi. Một mặt, bạn tối ưu hệ thống theo đúng nhu cầu của mình. Mặt khác, nếu cả đội không thống nhất trước các quy ước rõ ràng, dự án trượt rất nhanh thành một mớ code rối và nợ kỹ thuật cứ thế dồn lại. Tôi cho rằng đây mới là câu hỏi quyết định bạn có nên chọn Express hay không, chứ không phải mấy dòng benchmark.

Đổi lại, cái được thì rõ. Viết bằng JavaScript thuần nghĩa là client và server nói cùng một ngôn ngữ, đỡ hẳn khoản chuyển ngữ cảnh khi bạn ôm cả hai đầu. Dựa lưng vào hệ sinh thái npm khổng lồ, gần như bài toán nào cũng có sẵn package để lắp vào.

Một ứng dụng Express tối thiểu trông như thế nào?

Khởi tạo một server Express chỉ cần vài dòng:

javascript
const express = require("express");
const app = express();
const port = 3000;
 
app.get("/", (req, res) => {
  res.send("Hello World!");
});
 
app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

Đối tượng app là thực thể chính, do hàm express() tạo ra. Phương thức app.get nhận hai tham số: đường dẫn và một hàm callback xử lý. Callback này nhận hai đối tượng cốt lõi: req chứa mọi thông tin từ phía client, còn res dùng để phản hồi.

Khi trình duyệt gửi request đến port 3000 với đường dẫn /, Express khớp route rồi chạy callback tương ứng. Lệnh res.send vừa gửi dữ liệu về client, vừa tự thiết lập các header cần thiết và kết thúc chu kỳ request-response. Nhờ vậy kết nối không bị treo.

Riêng app.listen có một thay đổi đáng lưu ý ở Express 5: khi server gặp lỗi, callback bạn truyền vào sẽ được gọi kèm theo lỗi đó, thay vì lỗi bị ném ra như ở bản 4. Trách nhiệm xử lý chuyển về phía callback, nên hãy kiểm tra tham số lỗi trước khi hồn nhiên log dòng "đang lắng nghe".

Middleware: cơ chế cốt lõi của Express

Middleware là các hàm trung gian nằm giữa request và response, những chốt kiểm soát trong luồng xử lý. Một hàm middleware tiêu chuẩn nhận ba tham số: req, resnext. Nó chạy logic của mình (xác thực, ghi log, đọc body), rồi hoặc kết thúc chu kỳ bằng một lệnh phản hồi, hoặc gọi next() để chuyển quyền cho hàm kế tiếp trong stack. Bỏ qua cả hai, request sẽ treo vô thời hạn.

Request đi qua chuỗi hàm middleware (req, res, next) trước khi tới response, với ba nhóm middleware tích hợp sẵn, bên thứ ba và tự viết

Express phân middleware thành ba nhóm:

  1. Middleware tích hợp sẵn: Express đóng gói sẵn năm hàm. express.static phục vụ file tĩnh, express.json đọc body dạng JSON, express.urlencoded đọc dữ liệu form, cùng express.rawexpress.text cho payload dạng Buffer và văn bản.
  2. Middleware bên thứ ba: cài từ npm, ví dụ morgan để ghi log request hay cookie-parser để đọc cookie.
  3. Middleware tự viết: phần logic nghiệp vụ riêng của bạn.

Thứ tự khai báo là yếu tố sống còn, vì Express chạy middleware đúng theo trình tự chúng xuất hiện trong code. Lỗi phổ biến nhất: đặt express.json() sau các route handler, thế là req.body thành undefined. Không log, không cảnh báo. Bạn cứ thế ngồi soi xem dữ liệu bốc hơi ở đâu. Tương tự, đặt error handler lên trên các route thì nó sẽ chẳng bao giờ bắt được lỗi từ những route đó.

Một middleware ghi log đơn giản trông như sau:

javascript
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
  next();
});

Định tuyến và express.Router

Định tuyến quy định server phản hồi ra sao với từng endpoint, theo từng phương thức HTTP cụ thể: GET, POST, PUT, DELETE. Express ánh xạ chúng qua app.METHOD(). Ngoài ra còn app.all(), dùng khi bạn muốn áp một logic chung cho mọi phương thức tại cùng một đường dẫn, chẳng hạn bắt buộc xác thực.

Express ánh xạ phương thức HTTP tới đường dẫn qua app.METHOD(), còn express.Router tách từng cụm tính năng thành ứng dụng con gắn vào ứng dụng chính

Express cho phép trích dữ liệu động qua tham số route. Với route /users/:id, giá trị thật nằm ở req.params.id. Đây là nền tảng của mọi API RESTful. Ở Express 5, phần khớp đường dẫn chuyển sang path-to-regexp v8 với cú pháp chặt hơn hẳn: ký tự đại diện phải được đặt tên (/*splat thay vì /*), và đoạn tùy chọn dùng cặp ngoặc nhọn {} thay cho dấu ? trước đây. Nếu bạn đang nâng cấp từ bản 4, đây là chỗ tôi khuyên nên rà lại trước tiên.

Khi ứng dụng lớn dần, express.Router gần như bắt buộc. Router hoạt động như một ứng dụng con: bạn tách logic của từng cụm tính năng (/users, /orders) ra file riêng, rồi gắn vào ứng dụng chính bằng app.use(). Khi lồng router vào nhau, tham số của route cha mặc định không truyền xuống; thêm tùy chọn { mergeParams: true } lúc khởi tạo Router để route con đọc được chúng.

Xử lý lỗi trong Express

Express có sẵn một bộ xử lý lỗi mặc định nằm cuối stack middleware. Lỗi nào phát sinh mà không ai bắt sẽ rơi vào đó và trả về mã 500. Ở môi trường phát triển, nó kèm luôn stack trace; khi NODE_ENV đặt là production, phần stack trace bị lược đi. Đó đúng là hành vi bạn muốn, vì đẩy stack trace về client là một lỗ hổng bảo mật thực sự.

Lỗi rơi xuống middleware bốn tham số (err, req, res, next) khai báo cuối stack, rồi tới bộ xử lý lỗi mặc định của Express

Cải tiến lớn nhất của Express 5 là tự động bắt lỗi từ những Promise bị reject trong handler async. Bạn không còn phải bọc mọi thứ trong try-catch rồi gọi next(err) thủ công như ở bản 4. Riêng khoản này thôi đã đủ lý do để nâng cấp. Nhưng với các API kiểu callback cũ như fs.readFile, bạn vẫn phải tự bắt lỗi và đẩy vào next(err).

Một middleware xử lý lỗi tự viết luôn phải có đủ bốn tham số: (err, req, res, next). Thiếu tham số err, Express xem đây là middleware thường và bỏ qua toàn bộ logic xử lý lỗi bạn viết. Nó cũng phải được khai báo sau cùng, sau tất cả app.use() và route. Một chi tiết dễ quên: nếu lỗi xảy ra khi header đã gửi đi rồi, hãy gọi next(err) để nhường lại cho bộ xử lý mặc định đóng kết nối.

Express 5 khác Express 4 ở đâu?

Express 5 tập trung hiện đại hóa phần lõi và giảm nợ kỹ thuật, chứ không thêm tính năng mới:

  1. Yêu cầu hệ thống: cần Node.js 18 trở lên.
  2. Loại bỏ phương thức cũ: app.del() bị xóa hẳn, thay bằng app.delete(). req.param() cũng biến mất, buộc bạn truy cập tường minh vào req.params, req.query hoặc req.body. res.sendfile() đổi thành res.sendFile().
  3. Chuẩn hóa tên phương thức: req.acceptsCharset() thành req.acceptsCharsets(), tương tự với Encodings và Languages.
  4. Thay đổi về khớp đường dẫn: ký tự đại diện bắt buộc phải có tên, và dấu ? không còn dùng được trực tiếp trong chuỗi đường dẫn.
  5. Thay đổi MIME type: file .js nay được phục vụ với MIME type text/javascript thay vì application/javascript.
  6. Mặc định mới: express.urlencoded đặt tùy chọn extended về false, và express.static.mime không còn được export, dùng package mime-types độc lập thay thế.

So sánh Express 4 và Express 5: các phương thức cũ bị loại bỏ đặt cạnh dạng thay thế mới

Đội Express cung cấp sẵn bộ codemod tự động hóa phần lớn việc chuyển đổi, chạy qua @expressjs/v5-migration-recipe. Được đến đâu hay đến đó; riêng phần khớp đường dẫn thì vẫn nên tự soi lại bằng mắt.

Express có còn được duy trì tốt không?

Có, và rõ rệt hơn nhiều người nghĩ. Năm 2024, Express đạt trạng thái "Impact Project" của OpenJS Foundation, mức ghi nhận vai trò then chốt của dự án trong hệ sinh thái JavaScript. Technical Committee được bổ sung tám thành viên mới, trong đó có Blake Embrey, Ulises Gascón và Wes Todd.

Bảo mật trở thành trụ cột chính. Đợt kiểm toán bảo mật năm 2024 khiến dự án áp dụng OSSF Scorecard để theo dõi sức khỏe theo thời gian thực. Với các tổ chức còn chạy phiên bản cũ, Express hợp tác cùng HeroDevs cung cấp gói hỗ trợ dài hạn để tiếp tục vá bảo mật.

Lộ trình 2025–2026, với hậu thuẫn từ Sovereign Tech Fund, xoay quanh ba việc: tự động hóa quy trình phát hành trên npm để bớt sai sót thủ công, chuyển sang scoped package @expressjs/ để quản lý hệ sinh thái gọn hơn, và tối ưu sâu phần lõi. Nhóm kỳ vọng những cải tiến hiệu năng này hoàn tất vào giữa năm 2026. Với một dự án nhiều năm bị đồn là đã ngủ đông, đó là một quãng hồi sức đáng nể.

Khi nào nên chọn Express — và khi nào không?

Chọn Express khi bạn cần sự linh hoạt tối đa và muốn kiểm soát chi tiết từng thành phần trong middleware stack. Nó là lựa chọn tự nhiên cho các API nhẹ, microservice và những dịch vụ trung gian. Ở những chỗ đó, một framework đồ sộ chỉ làm vướng chân.

Khi nào nên chọn Express và khi nào không: API nhẹ cần kiểm soát chi tiết đặt cạnh đội đông người cần framework dọn sẵn quy ước

Đừng chọn Express nếu bạn muốn một framework dọn sẵn mọi thứ, có cấu trúc chuẩn và quy ước rõ ràng ngay từ đầu để đội đông người khỏi phải tự thiết kế kiến trúc. Express đưa cho bạn quyền tự quyết, và đi kèm quyền đó là trách nhiệm giữ cho kiến trúc khỏi rối. Nếu đội bạn chưa sẵn sàng nhận phần trách nhiệm ấy, hãy chọn thứ khác.

Tài liệu tham khảo

Chia sẻ bài viết

X / TwitterFacebookLinkedIn