- Gần đây, Node.js đang phát triển rất nhanh khi tích hợp ngay trong runtime những tính năng trước đây chỉ có thể dùng qua gói npm
- Nhờ đó có thể giảm rủi ro bảo mật chuỗi cung ứng, cải thiện tính di động của mã nguồn, giảm số lượng phụ thuộc, đơn giản hóa bảo trì, đồng thời góp phần đảm bảo hiệu năng và độ ổn định trong môi trường production
- Các API toàn cục như
fetch(), WebSocket, node:test đã được bổ sung, cho phép phát triển mà không cần các gói nổi tiếng như node-fetch, ws, mocha
- Nhờ mở rộng tính năng hệ thống tệp, Node.js cung cấp các tùy chọn
fs.glob(), fs.rm(), fs.mkdir() để thay thế glob, rimraf, mkdirp
- Trong nhóm API tiện ích và mật mã, các hàm như
crypto.randomUUID(), util.styleText(), atob/btoa đã được đưa vào chuẩn, khiến các gói như uuid, chalk không còn cần thiết
- Một số tính năng (
node:sqlite, URLPattern, --env-file, chạy TypeScript, v.v.) vẫn còn ở giai đoạn thử nghiệm
- Điểm quan trọng là với sự tự phát triển của Node.js, chỉ với runtime mặc định cũng đã có thể xây dựng ứng dụng hiện đại
Các gói npm chính đã được thay thế bằng tính năng tích hợp của Node.js
- Trước đây Node.js phụ thuộc vào nhiều gói npm khác nhau như tiện ích HTTP, helper cho hệ thống tệp, v.v.
- Tuy nhiên, trong các phiên bản gần đây (v18~v22), xu hướng tích hợp trực tiếp các tính năng này vào runtime ngày càng mạnh hơn
- Nhờ đó, độ phức tạp của việc quản lý package và rủi ro phơi lộ bảo mật đều giảm xuống
1. node-fetch → Global fetch()
- Từ Node.js 18,
fetch() giống hệt trên trình duyệt được cung cấp dưới dạng hàm toàn cục
- Có thể xử lý yêu cầu HTTP mà không cần
node-fetch
- Được giới thiệu thử nghiệm ở v17.5.0 và ổn định ở v18.0.0
- Tuy nhiên, với các phiên bản trước 18 thì vẫn cần
node-fetch
2. ws → Global WebSocket
- Từ Node.js 21, lớp
WebSocket toàn cục hỗ trợ kết nối WebSocket phía client
- Được thêm vào ở dạng thử nghiệm từ v21.0.0 và đến nay vẫn đang trong giai đoạn thử nghiệm
- Với triển khai WebSocket phía server, vẫn cần dùng gói
ws hoặc các thư viện liên quan
3. Framework kiểm thử → node:test
- Từ Node.js 18, có test runner tích hợp
node:test để thay thế mocha, jest v.v.
- Được giới thiệu thử nghiệm ở v18.0.0 và ổn định ở v20.0.0
- Hỗ trợ viết và chạy các bài kiểm thử đơn vị cơ bản
- Nếu cần snapshot, mocking, hệ plugin phong phú thì các framework bên thứ ba vẫn hữu ích
- Đủ tốt cho kiểm thử ở cấp độ module, nhưng với phát triển ứng dụng full-stack thì các framework hiện có vẫn có ưu thế riêng
4. sqlite3 / better-sqlite3 → node:sqlite
- Node.js đang đưa vào module
node:sqlite ở trạng thái thử nghiệm để truy cập SQLite
- Giải quyết các vấn đề biên dịch và lỗi khi nâng cấp thường gặp ở các gói native binding hiện có
- Hỗ trợ các tác vụ cơ bản như tạo cơ sở dữ liệu trong bộ nhớ, tạo bảng
- Vì vẫn còn ở giai đoạn thử nghiệm, nếu cần tinh chỉnh hiệu năng nâng cao hoặc tính năng bổ sung thì nên dùng các gói từ cộng đồng
5. chalk / kleur → util.styleText()
- Từ Node.js 20.12.0, có thể tạo kiểu văn bản trên console bằng
util.styleText()
- Ổn định từ v22.17.0
- Áp dụng các kiểu văn bản cơ bản như màu sắc, in đậm, gạch chân
- Nếu cần theme phức tạp, cú pháp chaining, khả năng tương thích ngược, vẫn có thể tiếp tục dùng
chalk v.v.
6. strip-ansi → util.stripVTControlCharacters()
- Node.js cung cấp sẵn hàm loại bỏ mã escape ANSI
- Xóa an toàn các ký tự điều khiển khỏi log
- Bao phủ hầu hết các trường hợp sử dụng bằng tính năng native, nên không cần package bên thứ ba
7. glob → fs.glob()
- Từ Node.js 22, Node.js bổ sung
fs.glob() tích hợp để tìm tệp theo pattern
- Được thêm ở v22.0.0 và ổn định trong v22.17.0 LTS
- Tìm tệp bằng các glob pattern như
**/*.js
- Nếu cần tương thích với các phiên bản Node.js cũ, hãy dùng package
glob
8. rimraf → fs.rm({ recursive: true })
- Node.js hỗ trợ xóa thư mục đệ quy bằng API native
- Triển khai bằng các tùy chọn
recursive, force của fs.rm()
- Có thể dùng từ khoảng v12.10.0 và hiện đã ổn định trong mọi phiên bản LTS
- Có thể xóa thư mục an toàn mà không cần package
rimraf
9. mkdirp → fs.mkdir({ recursive: true })
- Node.js cung cấp tạo thư mục đệ quy qua tùy chọn
recursive của fs.mkdir()
- Được thêm từ v10.12.0 và đã ổn định từ lâu
- Có thể tạo thư mục lồng nhau mà không cần package riêng
10. uuid → crypto.randomUUID()
- Từ Node.js 14.17.0, Node.js cung cấp hàm tạo UUID
crypto.randomUUID()
- Được tích hợp như một tính năng ổn định của module mật mã
- Có thể tạo ID ngẫu nhiên an toàn mà không cần package
uuid
11. base64-js / atob → atob, btoa
- Từ Node.js 20, có các hàm toàn cục
atob, btoa
- API mã hóa/giải mã Base64 giống hệt trên trình duyệt
- Cung cấp thêm lựa chọn ngoài
Buffer hiện có
- Có thể xử lý Base64 mà không cần polyfill
12. url-pattern → URLPattern
- Từ Node.js 20, API toàn cục
URLPattern được cung cấp ở dạng thử nghiệm
- Hỗ trợ route matching, trích xuất tham số đường dẫn, v.v.
- Vẫn cần thêm thời gian để ổn định
- Có thể xử lý khớp mẫu URL bằng Web API tiêu chuẩn
13. dotenv → --env-file flag
- Từ Node.js 20.10.0, hỗ trợ nạp biến môi trường bằng flag
--env-file
- Có thể nạp trực tiếp tệp
.env khi chạy
- Hiện vẫn ở giai đoạn thử nghiệm
- Nếu cần các tính năng nâng cao như mở rộng biến, nhiều tệp env, vẫn cần package
dotenv
14. event-target-shim → EventTarget
- Từ Node.js 15.0.0, Node.js cung cấp toàn cục hệ thống sự kiện chuẩn Web
EventTarget
- Ổn định từ v15.4.0
- Hỗ trợ mô hình xử lý sự kiện giống trình duyệt
- Có thể dùng như một lựa chọn thay thế cho
EventEmitter
15. tsc → Chạy TypeScript trong Node.js
- Từ Node.js 21, có thể chạy trực tiếp tệp
.ts bằng flag --experimental-strip-types
- Chỉ loại bỏ kiểu, không hỗ trợ type checking đầy đủ
- Vẫn đang ở giai đoạn thử nghiệm
- Với build production, kiểm tra kiểu tĩnh, tạo declaration file, type checking đầy đủ, vẫn cần
tsc
Kết luận
- Hướng phát triển của Node.js là giảm phụ thuộc vào package bên ngoài và nâng cao mức độ hoàn thiện của chính nền tảng
- Trên phiên bản LTS mới nhất (v22), rất nhiều package npm đã trở nên không cần thiết,
điều này đồng nghĩa với cải thiện lớn về bảo mật, hiệu năng và khả năng bảo trì
- Trong môi trường vận hành doanh nghiệp, các giải pháp như N|Solid đang được dùng để theo dõi những thay đổi này theo thời gian thực
- Phân tích hiệu năng tải công việc thực tế của các tính năng tích hợp (
fetch, node:test, crypto.randomUUID() v.v.)
- Tác nhân AI N|Sentinel giám sát mức sử dụng và đưa ra khuyến nghị tối ưu ở cấp độ mã nguồn
6 bình luận
Các API do runtime cung cấp ngày càng nhiều hơn..
Đặc biệt là các API như mạng, URL,
b64và các API xử lý chuỗi, v.v...Cái này đúng là... PH..
Có vẻ như UUID v7 vẫn còn hơi sớm.
Tôi nghĩ driver DB nên được nhìn từ một góc độ khác với các chức năng đáng ra phải nằm trong những thư viện cơ bản khác. Vậy tại sao cả Bun lẫn Node.js đều cố nhúng driver SQLite vào runtime?
Có phải vì Python cũng tích hợp sẵn không?
Tôi nghĩ thay vì nhúng sẵn tính năng SQLite thì việc tạo ra một tiêu chuẩn giao diện cho DB driver còn quan trọng hơn.
Chẳng phải vấn đề là giao diện của từng driver đều khác nhau, nên nếu muốn hỗ trợ nhiều loại DB thì rất khó nếu không dùng ORM sao?
Có lẽ họ đưa vào vì với các dịch vụ nhỏ cỡ blog cá nhân thì chỉ dùng sqlite thường là đã đủ. Có thì vẫn tiện.
Theo tôi, có lẽ họ đưa
sqlitevào vì giao diện của nó là đơn giản nhất và có thể trở thành một tài liệu tham chiếu tốt.Ngoài ra, tôi cũng không rõ vì sao lại cần phải tạo ra một tiêu chuẩn cho giao diện DB Driver như anh nói. Tôi nhớ mang máng là đã từng thấy thứ gì đó tương tự trong PHP.
Những truy vấn phức tạp mà ORM không xử lý được thì đến giờ tôi vẫn đang dùng truy vấn RAW...
Có vẻ bạn thường xuyên phải dùng nhiều loại DB khác nhau nhỉ... Hay là thử tự làm một thư viện xem? :)
Việc runtime tạo ra tiêu chuẩn giao diện cho DB driver như
python,java,c#,gov.v. là chuyện khá phổ biến.Nhưng với Node thì ngay cả các driver cùng nhắm tới
sqlite, việc thực thi statement cũng khác nhau nhưexecute()hoặcexec(), nên chỉ riêng chuyện thay driver thôi cũng đã phải sửa lại ở một mức độ nhất định.Dù không phải chuyện xảy ra thường xuyên, nhưng khi đổi DB thì cũng khá bất tiện.
Giả sử đang dùng
mysqlnhưng không thích cáchOraclelàm, hoặc cần một extension nào đó chỉ có ởpostgresqlnên chuyển sangpostgresql,nếu có giao diện tiêu chuẩn như
jdbcthì chỉ cần kiểm tra lại SQL, còn trong hệ Node thì tác dụng phụ là phải đập đi làm lại toàn bộ logic gọi DB.+Anh/chị đã khuyên tôi thử tự làm một thư viện, nhưng khi có tiêu chuẩn giao diện chung thì lúc làm thư viện sẽ thuận tiện hơn.
Công ty tôi dùng
java, và trong framework nội bộ phải hỗ trợmysql,db2,oracle,mssql, nên khi bảo trì adapter cho từng DB, tôi đã được hưởng lợi rất nhiều từ tiêu chuẩnjdbc.