Node.js 21 正式發布,趕緊來看看有哪些更新吧!
版本說明
這兩個版本有什么區別呢?Node.js 21 適合在特定環境下進行早期功能測試,而 Node.js 20 LTS 則適用于生產部署。Node.js 21 將在未來 6 個月內成為“當前”版本,直到 2024 年 4 月。以下是完整的 Node.js 發布計劃。
Node.js 的發布可以分為三個階段,奇數版本號的發布線路不會被提升為 LTS 版本,也就不會經歷“Active LTS”和“Maintenance”階段。
- Current(當前):包含大部分進入 nodejs/node 主分支的非主要(非破壞性)變更。
- Active LTS(活躍長期支持):新功能、錯誤修復和經LTS團隊審核后被確定適合該發布線路且穩定的更新。
- Maintenance(維護):關鍵錯誤修復和安全更新。新功能可能會根據LTS團隊的判斷加入。通常只在新功能支持遷移到后續發布線路的情況下才會添加。
如果你想要嘗試最新的Node.js功能,那么 Node.js 21 是個很好的測試平臺,它提供了即將到來的新特性的先期體驗。Node.js 的發布計劃特別關注這一點。但是如果正在準備或已經在生產環境中使用 Node.js,則應該選擇較穩定的版本,如Node.js 20 和 18 LTS。這些版本可以保證可靠性和穩定性,并且會在較長時間內得到支持和維護。
Node.js 21 的亮點包括將 V8 JavaScript 引擎升級到 11.8 版本,穩定的WebStreams和 fetch功能,一個用于更改模塊默認值的新實驗性標志(--experimental-default-type),對測試運行器的許多更新,內置 WebSocket 客戶端等!
主要更新
穩定的WebStreams和 fetch功能
Node.js 21 對fetch模塊和WebStreams進行了重要更新,并將它們標記為穩定版本。
這一變化影響到了WebStreams、FormData、Headers、Request、Response和fetch等模塊。
內置 WebSocket 客戶端
這個版本新增了一個實驗性的瀏覽器兼容的 WebSocket 實現,可以通過使用參數--experimental-websocket來開啟。但是,像所有實驗性功能一樣,它可能會隨時發生變化。
V8 11.8
按照慣例,Node.js 21 中包含了新版本的 V8 引擎(更新到版本11.8,該版本是 Chromium 118 的一部分),帶來了性能的改進和新的語言功能,包括:
- 數組分組
- ArrayBuffer.prototype.transfer
- 擴展的 WebAssembly 常量表達式
Node.js 測試運行器支持通配符
在 Node.js 21 中,測試運行器引入了對通配符表達式的支持。通配符是一種模式語法,可以用來匹配多個文件路徑。在測試過程中,可以使用通配符表達式來指定要運行的測試文件。
通過使用通配符表達式,可以更方便地選擇和執行特定類型的測試文件,而不需要一個個地指定它們的路徑。例如,如果想運行所有具有.test.js文件擴展名的文件,無論這些文件位于哪個目錄下,可以使用類似于node --test **/*.test.js的命令。這樣,測試運行器會自動匹配并執行符合該模式的測試文件。
ESM:支持改變模塊默認值
experimental-default-type 是 Node.js 的一個實驗性特性,可以用來切換默認的模塊系統。這意味著開發者可以使用不同的模塊類型,并在需要時進行切換,使得 Node.js 應用更加靈活,能夠應對不同的場景。
標志 --experimental-default-type=module 用于將模塊類型切換成 ES 模塊。對于已經明確定義為 ES 模塊或 CommonJS 的代碼,例如在 package.json "type" 字段中或文件擴展名為 .mjs/.cjs 或 --input-type 標志等,不會受到影響。在使用 --experimental-default-type=module 標志時,原本默認解析為 CommonJS 的代碼將被解析成 ES 模塊。
此外,Node.js 團隊還在探索使用檢測 ES 模塊語法作為Node.js識別文件是否為ES模塊的一種方式,目標是最終找到一種支持ES模塊語法的方法,并盡可能減少變更。
模塊自定義鉤子 globalPreload 已被移除,改用 register 和 initialize
模塊自定義鉤子 globalPreload 已被移除。取而代之的是,使用 register 方法將數據從應用線程發送到自定義鉤子,并使用 initialize 鉤子在線程之間建立通信通道。
fs.writeFile 函數添加 flush 選項
在寫入文件時,有可能數據并不會立即刷新到永久存儲中。這可能導致后續讀取操作看到舊的數據。該版本為 fs.writeFile 系列函數添加了一個 flush 選項,該選項可以在成功寫入操作結束時強制刷新數據到永久存儲。
性能
性能是一個運行時的重要屬性,@nodejs/performance 團隊在過去一年中一直努力改進 URL、fetch、streams、node:fs 和 HTTP 等方面的性能。
Streams
Node.js 流團隊不斷優化可寫流和可讀流。在這個版本中,通過移除冗余檢查、利用位圖以及以更高效的方式安排回調來進一步優化流操作。
HTTP
在此之前,當向分塊響應寫入數據時,無論響應是否處于 corked 狀態,Node.js 都會為每個 .write(...)調用創建一個單獨的數據塊。這會在客戶端和服務端都產生不必要的開銷。
該更新通過在取消 corked 狀態時,為所有 write(...) 調用創建一個單一的數據塊來解決了這一問題。
考慮以下基于 Transfer-Encoding 文檔的示例:
res.cork();
res.write('Mozilla');
res.write(' Developer Network');
res.uncork();
在每個數據塊的開頭,您需要以十六進制格式添加當前數據塊的長度,然后跟著 '\r\n',再接著是數據塊本身,最后再加上另一個 '\r\n'。終止塊是正常的數據塊,唯一的例外是它的長度為零。
最終生成的響應流為:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7\r\n
Mozilla\r\n
18\r\n
Developer Network\r\n
0\r\n
\r\n
在 Node.js 21 中,當取消 corked 狀態時,所有數據塊都會合并成一個單獨的數據塊,從而減少了很多不必要的開銷。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25\r\n
Mozilla Developer Network\r\n
0\r\n
\r\n
llhttp 9.1.2 強制嚴格模式執行
- 在以前的 Node.js 版本中,默認情況下未啟用嚴格模式。在 Node.js 21 中,強制執行了以前包含在嚴格模式中的所有設置,提高了代碼的可靠性和安全性。
- 現在,標頭后面必須有 \r\n(之前允許單獨使用 \r)。此外,數據塊后必須有 \r\n,以確保一致的數據處理。
- 在解析帶有 Connection: close 標頭的消息后不再允許傳輸數據。這一變化增強了協議遵從性并改善了連接處理。
為適應特定的用例,引入了--insecure-http-parser 標志。該選項允許用戶禁用上述更改,并保持與以前的解析行為的向后兼容性。
這些更新旨在增強整個系統的穩定性,并改善 Node.js 應用的數據處理一致性。鼓勵開發人員審查其代碼庫并相應地調整其實現,以確保與最新版本的無縫集成。
navigator 對象集成
在 Node.js 21 中,引入了全局 navigator 對象,增強了 Web 的互操作性。現在,可以通過 navigator.hardwareConcurrency 訪問硬件并發信息。