Node.js đã bước sang phiên bản chính thứ 24, mang theo một loạt tính năng mới và cải tiến. Bản phát hành này sẽ là bản Current trong sáu tháng tới và sẽ trở thành LTS vào tháng 10 năm 2025. Hãy cùng điểm qua những điểm nổi bật trong phiên bản này.
Nâng cấp V8 lên 13.4 Với việc nâng cấp thư viện phụ thuộc cho phép Node.js chạy JavaScript, giờ đây chúng ta có thể truy cập một vài tính năng mới để viết mã an toàn và hiệu quả hơn.
1. Error.isError
Error.isError
là một phương thức tĩnh dùng để kiểm tra xem một giá trị có phải là một thể hiện (instance) của Error hay không, bất kể nó nằm trong "realm" (bối cảnh) nào.
Chắc hẳn bạn (hoặc ai đó bạn biết) đã từng rơi vào cái bẫy khi dùng instanceof để kiểm tra xem một lỗi có phải là Error không, nhưng lại bị trả về false trong khi bạn rất chắc rằng đó là lỗi.
Ví dụ như sau:
const vm = require('node:vm'); function logError(err) { if (err instanceof Error) { console.error('Caught an error:', err); } else { console.error('You must provide an Error instance'); }
} const context = vm.createContext(); try { vm.runInContext(` throw new Error("Something went wrong in another realm"); `, context);
} catch (err) { logError(err); // Kết quả không đúng: "You must provide an Error instance"
}
Đây là đặc điểm tự nhiên của JavaScript. Trước đây rất khó để có một hệ thống xử lý lỗi tập trung có thể bắt được lỗi từ nhiều "realm" khác nhau. Mọi thứ giờ đây trở nên đơn giản hơn với phương thức mới này.
Hãy thay đổi hàm logError, sử dụng Error.isError thay cho instanceof để hoạt động chính xác:
function logError(err) { if (Error.isError(err)) { console.error('Caught an error:', err); } else { console.error('You must provide an Error instance'); }
}
2. Quản lý tài nguyên rõ ràng (explicit) với using, using await
Tính năng quản lý tài nguyên rõ ràng mang đến cú pháp và ngữ nghĩa mới cho JavaScript, giúp quản lý vòng đời của tài nguyên như: file handle, kết nối mạng hoặc con trỏ cơ sở dữ liệu. Đặc biệt hữu ích để đảm bảo tài nguyên được giải phóng đúng cách, kể cả khi có lỗi xảy ra hoặc thoát sớm.
Thay vì làm thế này:
function someFunction() { const handle = someResource.open(); try { // có thể dùng handle ở đây } finally { handle.close(); }
}
Giờ bạn có thể làm như sau:
function someFunction() { using handle = someResource.open(); // có thể dùng handle ở đây
} // handle sẽ tự động được đóng khi ra khỏi scope
Một tài nguyên sẽ có thể được "dispose" nếu nó có phương thức Symbol.dispose. Nếu dispose là bất đồng bộ, thì phải định nghĩa bằng Symbol.asyncDispose.
Nếu là bất đồng bộ, bạn phải dùng using await thay vì chỉ using.
Đây là cải tiến tuyệt vời để viết mã rõ ràng, dễ bảo trì và tránh rò rỉ tài nguyên hoặc các lỗi phát sinh khác do không quản lý tài nguyên đúng cách.
3. Atomics.pause
Atomics.pause
cho phép bạn báo hiệu cho CPU rằng luồng hiện tại đang chờ tài nguyên, ví dụ như trong một vòng lặp khóa chờ (spinlock). Điều này giúp CPU tối ưu hóa việc sử dụng năng lượng và hiệu năng.
const sab = new SharedArrayBuffer(1024);
const i32 = new Int32Array(sab); let spin = 0;
do { if (acquiredSharedResourceLock()) { break; } Atomics.pause(); spin++;
} while (spin < 10); // Trường hợp chậm hơn: chờ khóa (chỉ dùng trong worker thread)
Atomics.wait(i32, 0, 1);
4. WebAssembly hỗ trợ bộ nhớ 64-bit
Giới hạn bộ nhớ của WebAssembly được nâng từ 4GB lên đến 16 exabyte. Đây là một bước nhảy vọt, đặc biệt hữu ích với những ứng dụng cần lượng lớn bộ nhớ.
5. Hệ thống phân quyền (Permission) đã ổn định
Mô hình phân quyền trong Node.js là cơ chế hạn chế truy cập đến các tài nguyên cụ thể khi chạy ứng dụng. API này tồn tại phía sau cờ --permission. Khi bật, nó sẽ giới hạn quyền truy cập theo mặc định.
Bạn có thể dùng API runtime để kiểm tra quyền truy cập:
// index.js
process.permission.has('fs.write'); // true
process.permission.has('fs.write', '/home/codeminer42/writeonly'); // true
process.permission.has('fs.write', '/home/codeminer42/readonly'); // false process.permission.has('fs.read'); // true
process.permission.has('fs.read', '/home/codeminer42/writeonly'); // false
process.permission.has('fs.read', '/home/codeminer42/readonly'); // true
Chạy script trên với lệnh:
node --permission --allow-fs-read=/home/codeminer42/readonly --allow-fs-write=/home/codeminer42/writeonly index.js
6. URLPattern có sẵn toàn cục
API URLPattern giờ có thể truy cập trực tiếp từ đối tượng toàn cục (global object), không cần import. Đây là API mạnh mẽ dùng để khớp mẫu URL, tương tự như cách biểu thức chính quy (regex) hoạt động với chuỗi.
const pattern = new URLPattern({ pathname: "/books/:id" });
console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.exec("https://example.com/books/123").pathname.groups); // { id: "123" }
Rất hữu ích khi xác thực hoặc phân tích URL một cách có cấu trúc.
7. Những thay đổi khác
- Nâng cấp Undici lên
7.0.0
: Undici là thư viện phía sau fetch trong Node.js. Phiên bản mới này mang lại nhiều cải tiến về hiệu năng và sửa lỗi. - Nâng cấp npm lên
11.0.0
. Một vài thay đổi đáng chú ý:- npm init giờ có thêm câu hỏi về kiểu dự án, sắp xếp các trường trong package khác đi
- Lệnh npm hook bị loại bỏ
- Hỗ trợ Node ^20.17.0 hoặc >=22.9.0
Xem thêm chi tiết tại: https://github.com/nodejs/node/pull/57609