Node.js Next 10
?????♀??編者按:本文是 NodeParty 回顧文章之一,作者是 Node.js、V8 活躍貢獻者,阿里巴巴集團 TC39 代表吞吞,介紹了 Node.js 的工作組與戰(zhàn)略計劃,以及未來十年的發(fā)展,歡迎查閱~

其他 NodeParty 回顧文章:
大家好,今天很高興能夠在 NodeParty 和大家介紹 Node.js 的工作組與戰(zhàn)略計劃,以及未來十年的發(fā)展。我先做一個簡單的自我介紹,我是來自阿里巴巴淘系技術部的吞吞,目前是 CNCF OpenTelemetry 項目的維護者,同時也是Node.js、V8 的活躍貢獻者,阿里巴巴集團 TC39 代表。

在這次的分享中,我們會介紹如何跟蹤 Node.js 中正在發(fā)生的事情,和在跟蹤過程當中需要了解的發(fā)行計劃;了解我們跟蹤的特性會在哪一個版本當中發(fā)行;我們也會了解當前 Node.js 正在活躍維護的一些有趣的新特性;在這之后我們會了解一下當前比較活躍的工作組和戰(zhàn)略計劃。這些都是我們了解 Node.js 接下來會發(fā)生什么的重要窗口。在了解了當前活躍的工作之后,我們也會介紹一下如果我們有想要落地的特性,我們該如何將這些特性落地到 Node.js 上,參與到這些工作之中。
??Node.js 如何決定接下來發(fā)展路線?

Node.js 項目維護的基本方針是透明治理,也就是說它所有決策都是透明公開在? GitHub 倉庫上的。我們可以在 GitHub 的 Issue Tracker 當中去追蹤到它所有的決策過程。Node.js 技術指導委員(TSC)會也會將他們所有的討論公開在 GitHub 上。值得注意的是,Node.js TSC 中單個公司的雇員是不能超過 25% 的。也就是說這是一個去中心化的組織,它是由社區(qū)控制來驅動 Node.js 來發(fā)展的。也正是因為去中心化的組織架構,能夠讓 Node.js 集合所有人的興趣、愛好和利益點去推動 Node.js 的發(fā)展。
作為一個松散的組織,Node.js 官方其實是沒有一個明確路線圖。新特性通常是沒有具體的版本發(fā)布計劃,會隨著 Current/LTS 版本滾動發(fā)布。也就是說這些新特性完成了實現(xiàn)之后,那么它就會在下一個即將發(fā)布的版本當中隨之滾動發(fā)布。不過雖然它是一個松散組織,Node.js 也存在長期緊密合作的工作組和一些明確的戰(zhàn)略計劃。
??我該如何跟蹤 Node.js 進展?

如果想要去追蹤 Node.js 接下來需要發(fā)布的內容、接下來正在進行的進展,最便捷的方式就是關注 Node.js ?官方博客。每當一個新版本發(fā)布,或者是有重要的事項需要通知時,Node.js 官方博客上都會發(fā)布發(fā)行紀要或者公告。
除了官方博客,了解 Node.js 發(fā)展最直觀、最便捷的方式,當然是直接參與 GitHub 討論。而正如剛才所說,Node.js 的決策都是透明和公開的,我們可以在 GitHub 上看到它所有特性的實現(xiàn)過程與決策討論的過程。討論沒有任何的門檻。當然你必須要有一個 GitHub 賬號來進行討論。除此之外,還可以參與到各個工作組的定期工作會議了解當前工作組的工作進展。
??Node.js 版本發(fā)行

Node.js 主要有三個發(fā)行線,一個是 Nightly 版本,也就是我們熟知的 Main 分支,它每天都會有最新的版本打包出來可以讓開發(fā)者們試用。但這個發(fā)行通常也是最不穩(wěn)定的,可能會有各種奇奇怪怪的問題,不過是開發(fā)者們嘗試最新特性、最新修復的一個非常便捷的方式。
另一個是 Current 版本,每六個月都會從 Main 分支上切出新的 Major 版本作為 Current 版本。其中為 Major 版本號為偶數(shù)的 Current 版本,它會在發(fā)布當年的十月份被提升為 LTS 版本,也就是長期維護版本。
LTS 長期維護版本每 12 個月發(fā)布一次,它有 30 個月的長期維護期。在這 30?個月內,包含 12 個月的活躍特性支持。這 12 個月內只要 Main 分支上有任何新的特性,這個長期維護版本都能同樣獲得這些特性更新。在這 12 個月的活躍特性支持的周期過后,還有 18 個月的維護支持,如 Bug Fix、安全更新等。

剛才我們有提到,新特性通常不會有固定的發(fā)布計劃。他們會在這些特性實現(xiàn)之后,隨著 Current 和 LTS 版本固定的發(fā)布周期來滾動發(fā)布。這些新特性在合并到 Main 分支之前,他們會被標記為 SemVer Major 或者 SemVer Minor。通常來說他們都會被標記為 Semver Minor 版本,也就意味著他們會被發(fā)布到活躍支持的 LTS 版本上。比如目前 v16 是最新的 LTS 版本,v18 是 Current 版本,在今年 10 月份時 v18 將提升為 LTS 版本。v18 作為新的 LTS 版本發(fā)布時,它上面的一些新特性我們其實已經在 Node.js v16 上使用過一段時間了,可能已經是我們熟知的一些“老”特性。這也是 LTS 版本發(fā)布機制的一個好處。
??有趣的新特性

了解了 Node.js 的版本發(fā)布計劃后,我們接下來看一看最新的一些特性,如 ECMAScript Modules 新支持了 JSON Module、Module Loaders,以及在近期的 v17 中發(fā)布的 node:test 這種內置的測試驅動模塊,之前社區(qū)當中熱議的中立的模塊管理器的管理器 Corepack。Node.js ?也在努力做 Web API 的兼容性支持,比如說 Web Crypto, Fetch, Web Stream, WebAssembly, Web Worker 等等。
ECMAScript Module

自從 2015 年 ES6 發(fā)布以來,Node.js 一直在不斷改進 ECMAScript Module 支持,不斷地優(yōu)化 ECMAScript Module 與已經廣泛使用的 CommonJS 模塊互操作性,如在 ESM 中導入 CJS 模塊,或者在 CJS 中導入 ESM 模塊。現(xiàn)在對于模塊維護者來說,他們可以在 package.json 當中去聲明模塊類型為 module 類型。除此之外,他們也可以在 package.json 當中去聲明對于 CJS 和 ESM 來說,不同的入口模塊,這樣模塊維護者可以在一個 npm 包里面針對 CommonJS 和 ECMAScript Module 區(qū)分不同的入口。
Node.js 最近也已經支持了 ECMAScript 中的 JSON Modules。我們可以通過 import assertion 語法來去導入一個? JSON 模塊。
然后還有實驗性的 Module Loaders,現(xiàn)在我們可以同時使用多個 Module Loader。比如我們通過 http loader 像 deno 或者 Web 瀏覽器環(huán)境直接導入一個 Http 模塊?;蛘呤褂妙愃朴?CommonJS 中 tsnode 的 TypeScript Loader 導入 TypeScript 文件。Module Loader 特性還在持續(xù)地演進當中,后續(xù)也會支持更多的場景,比如在 ShadowRealm 中使用 Module Loader。
我們可以在 Loaders 工作組倉庫中去追蹤他們的 roadmap。
node:test

然后我們接下來看一下 v17 中正式落地到 Node.js 中的實驗性特性 node:test。我們現(xiàn)在可以使用 node 的提供的測試界面來寫測試用例,而不需要任何的第三方模塊。他提供的測試界面非常簡單,就是一個 test 函數(shù)。Node.js 也提供了 behavior driven test 中的 describe 和 it 的界面。我們可以通過命令行 node --test 來執(zhí)行這些測試。Node.js 輸出的測試報告是社區(qū)常見 tap 格式,我們可以使用各式各樣的 tap reporter 來解析測試輸出結果。
Corepack

Corepack 是中立的“模塊管理器”管理器。我們現(xiàn)在比較常用的像 npm,yarn,pnpm 或者 tnpm 都提供了兼容 Node.js 模塊查找邏輯的包管理能力。在 2022 年,npm 已經不再是 Node.js 項目安裝依賴的唯一工具。值得注意的是,npm 是一個私有公司項目,它不是托管于 OpenJS Foundation 等中立基金會、通過社區(qū)驅動管理的項目。所以作為 OpenJS Foundation 的中立項目,為了避免被一個特定私有公司所綁架、驅動,將 Corepack 作為 Node.js 內置的功能讓大家去有更多中立的選擇。
當然 Corepack 還可以將一個“模塊管理器”打包成一個壓縮包,然后我們就可以將這個壓縮包上傳到我們的生產環(huán)境當中,或者是一個特殊的網(wǎng)絡的環(huán)境中,然后將打包好的包管理器使用 Corepack 恢復出來,即可直接使用。具體的話也可以直接看 Corepack 的文檔。
??Node.js 工作組

工作組是驅動 Node.js 絕大多數(shù)特性落地實現(xiàn)的一個重要工作方式。Node.js 工作組都是公開的,比如工作組的工作會議都會在 Node.js 官網(wǎng)上的日歷中公開。參與這些工作會議是沒有任何門檻的,只要有大家有任何興趣,都可以直接去參與到他們的線上會議當中。
接下來我們會簡單介紹一下 undici,Node-APi, 還有診斷工作組。
Undici 工作組

我們剛才提到 Node.js 目前也正在活躍提供 Web API 的兼容性支持。其中 Fetch API 就是由這個工作組維護、支持。
undici 是 Node.js 現(xiàn)代化的一個HTP Client。相對于現(xiàn)在的 http 模塊來說,undici 模塊提供了更加現(xiàn)代化的 API。比如說他提供了 Web Fetch API 的支持, mock 請求能力的支持。如果我們想要攔截 http 模塊當中的一些發(fā)起的請求,我們可能需要去做 monkey patch,而通過 undici 提供的這個內置請求攔截能力,我們就不再需要去做 monkey patch。我們可以通過它提供的攔截器來去對請求做裝飾,或者對請求做本地的 mock 攔截。
當然它還提供了最新的 diagnostic channel 支持。這個我們會在等一會兒介紹診斷工作組的時候會去介紹這個特性。這個特性就是說我們常見的,比如像 APM,也就是比如社區(qū)常見的 OpenTelemetry,DataDog,或者是 Sentry,它們都可以通過 diagnostic channel 來對 undici 模塊做注入,然后去插入一些對于 APM 來說必要的信息,比如說在里面插一些 Trace ID 等等。同時 undici 也提供了內置的 Http Proxy 的支持。
undici 工作組主要就是維護 undici 包。Node.js 官方還維護了 undici 的 npm 包,可以通過 npm 安裝使用。
診斷工作組

診斷工作組主要工作是在 Node.js 當中去維護多種多樣的診斷能力。比如說 diagnostic channel,診斷報告等。診斷報告是人可讀的 JSON 格式的文件,如果在 Node.js 進程崩潰的時候,比如說出現(xiàn)了 fatal error,那它可以在進程退出前生成診斷報告。因為診斷報告是文本文件,我們可以直接去閱讀這個文件,不像核心轉儲是二進制的格式,需要一些特殊的工具去解析核心轉儲。
在上圖中的使用例子里面看到,我們可以通過 diagnostic channel 去訂閱 undici 的 request 創(chuàng)建事件,然后在這個 request 中注入 Trace Id 等等信息。上圖右下角是一個診斷報告的示例,我們可以看到它里面包含了報告版本,包含了報告的觸發(fā)原因,報告時間等等。當然還包含了進程的很多信息,比如 JavaScript 調用棧,C++ Native 的調用棧等等。
除了這兩個關鍵的特性之外,診斷工作組也維護了很多其他的診斷工具,比如說像 llnode 等等。
Node-API 工作組

除了剛才這兩個工作組之外,還有就是 Node-API 工作組。Node-API 是一個 ABI 穩(wěn)定的 Addon API,里面包含了 ECMAScript 語言常用的一些特性,比如說創(chuàng)建對象,創(chuàng)建 array 等。像 SWC,node-sqlite3,parcel, ?cbrypt 等等這些常見 npm 模塊目前都已經遷移到了 ?Node-API 來實現(xiàn) Node.js addon。Addon 使用了 Node-API 的話,在我們在切換 Node.js 版本之后,就不需要再重新 npm install 去編譯了。它是可以跨 Node.js 版本使用的,不像直接使用可能 breaking change 的 V8 API。
Node-API 是由 Node-API 工作組來長期維護,并保證 API/ABI 穩(wěn)定的。我們能夠通過 C、C++,還有其他如 Rust、Go 等等編程語言通過 Node-API 去編寫多種多樣的 Node.js Addon。Node.js 官方維護了一個 node-addon-api 的 npm 包,提供基于 Node-API 的現(xiàn)代化的 C++ API 封裝。
??戰(zhàn)略計劃

戰(zhàn)略計劃目前包括像 Core promise API,在 Node.js 中將以前傳統(tǒng)的基于 callback 的API 轉換成基于 Promise 的 API,讓他們更加現(xiàn)代化;像 HTTP3 的最新協(xié)議支持;ShadowRealm;Startup Performance;還有最新的 V8 版本支持。接下來主要是簡單介紹三個戰(zhàn)略計劃。
Startup Performance

在上周,我們剛好在 Node.js 中落地了在用戶態(tài)創(chuàng)建 Startup Snapshot 的 API。通過這個 API,我們可以獲得更快的啟動速度。比如我們業(yè)務當中可能常用到通過 vm 來做服務端渲染,或者是在通過 Node.js 來做 Serverless Runtime 等等,都可以受益于這個啟動性能優(yōu)化。
它主要是通過 V8 Startup Snapshot 機制來將 JavaScript 執(zhí)行狀態(tài)來保存到硬盤上。然后在下一次啟動的時候,快速地從保存的 Startup Snapshot 中反序列化出整一個JavaScript Heap。通過這種方式,啟動初始化過程中的 JavaScript 邏輯都不需要再重新執(zhí)行一遍,我們就可以從保存的 Startup Snapshot 中恢復出可執(zhí)行的狀態(tài)。
Startup Snapshot 除了提供的啟動速度的優(yōu)化之外,我們后續(xù)也會基于這個特性來實現(xiàn) Signle Executable Application,以期將 Node.js 應用打包成一個單獨的可執(zhí)行二進制文件,不再需要一大堆的 node_modules 等等。
ShadowRealm

ShadowRealm 目前也是一個 TC39 Stage 3 的提案。ShadowRealm 相對于目前 Node.js 提供的 vm 模塊來說,它提供了絕對的 JavaScript 對象交互隔離的執(zhí)行環(huán)境,對象逃逸、對象身份不連續(xù)等問題將得到解決。ShadowRealm 相比于 vm 來說,它內置了部分 Node.js 中常見的 API,比如 URL、TextEncoder 等等,也意味著在 ShadowRealm 執(zhí)行常見的 JavaScript 代碼將更加便捷。
ShadowRealm 支持原生的 ECMAScript Modules,并且 Realm 之間的 Module 緩存是互相獨立的。我們可以利用這個特性,實現(xiàn)如執(zhí)行插件代碼等等可信的二方腳本。這也是由我負責的一個戰(zhàn)略計劃。
Next-10

Next-10 戰(zhàn)略計劃是期望尋找接下來十年 Node.js 的工作方向。對于從這個戰(zhàn)略計劃來說,目前優(yōu)先級第一是去明確我們如何改進開發(fā)者體驗;第二是讓 Node.js 一直保持穩(wěn)定,能夠服務于更多的企業(yè)場景。目前正在討論的計劃有如在 Node.js 中集成執(zhí)行 TypeScript 文件的能力。目前 TypeScript 已經成為大家開發(fā) Node.js 應用常見的方案,很多開發(fā)者都或多或少的體驗到 TypeScript 比如說像類型提示等等好處。但因為 TypeScript 是由微軟主導的一個項目,Node.js 如何集成 TypeScript 將會是一個非常大的挑戰(zhàn)。我相信 Node.js 將會提供一個中立的選擇,讓開發(fā)者可以選擇去使用 TypeScript,也可以使用如 facebook 的 flow 等編程語言。
Openservability 也是一個非常重要的方面,比如說后續(xù)應用遷移到 ECMAScript Module之后,我們如何向 ECMAScript module 中通過類似于 CommonJS monkey patch 的方式注入觀測代碼等等。
這些都是 Next-10 戰(zhàn)略計劃正在活躍討論的話題。大家只要對這些有興趣,都可以在 Node.js slack 中 Next-10 Channel 里面去參與討論。
??成為 Node.js 的關鍵貢獻者

了解了這些戰(zhàn)略計劃和工作組之后,我們該如何去參與到這個工作當中去、成為 Node.js 的關鍵貢獻者呢?我們剛才提到最簡單就是參與 GitHub 討論,提交 PR,去評論,去發(fā)表你的看法。除了 Issue Tracker 上比較零散的一些課題之外,我們可以去參與到工作組當中,去參與他們的工作會議。工作組的會議基本上都是每周定期舉行的。我們可以直接在官方的日歷上看到他們的會議是在什么時間,線上參會鏈接等。
像 Node-API 的工作會議是北京時間每周五晚上十一點。Node-API 工作會議也是由我來主持的一個會議之一。
工作會議沒有門檻,如果有任何感興趣的話題,或者對 Node-API 有任何疑問,都可以直接加入這些會議。除了工作組之外,如果我們認為 Node.js 當前它還有一些領域還沒有人主導的,但是我們認為它非常重要,這個時候可以在 Node.js 的 Issue 中發(fā)起你認為重要的需求、發(fā)起你認為重要的戰(zhàn)略計劃和工作組。提交 Feature Request 或者是戰(zhàn)略計劃方案、工作組方案,都是沒有任何門檻的。只要你有想法、愿意去做這些事情,愿意去貢獻你的一份力量,你都可以去發(fā)起這些 Feature Request。所以如果我們想要決定 Node.js 接下來十年的發(fā)展方向的話,我非常推薦大家主動地去參與到社區(qū)的討論中去,主動發(fā)起需求,主動發(fā)起戰(zhàn)略計劃,然后主動去參與到工作組中去。
這些就是我們這次要分享的主要的內容,謝謝大家。
?? 相關鏈接:
Node.js 戰(zhàn)略計劃:
https://github.com/nodejs/node/blob/main/doc/contributing/strategic-initiatives.md
Node.js ?作組慣例?作會議:
https://nodejs.org/calendar