React 團隊最近在忙啥?
距離 React 最近一次版本更新已經過去了 8 個多月。那最近 React 都在忙些啥呢?下面就來看看 React 團隊最近正在研究的事,以及取得的進展!
概覽:
- React Server Components
- 資源加載
- 文檔元數據
- 離屏渲染
- Transition Tracing
React Server Components
React Server Components(RSC,服務端組件)是由 React 團隊設計的一種新的應用架構。
React 團隊正在引入一種新的組件——服務器組件,它提前運行并且被排除在 JavaScript 包之外。服務器組件可以在構建期間運行,從文件系統讀取或獲取靜態內容。它們還可以在服務端運行,無需構建 API 即可訪問數據層。可以通過 props 將數據從服務端組件傳遞到瀏覽器中的交互式客戶端組件。
RSC 將以服務端為中心的多頁面應用的簡單“請求/響應”心智模型與以客戶端為中心的單頁應用的無縫交互相結合,提供了兩全其美的體驗。
自上次更新以來,React 團隊合并了 React 服務端組件 RFC 以批準該提案。通過 [React Server Module Conventions](React Server Module Conventions) 提案解決了懸而未決的問題,并與合作伙伴達成共識以遵循“use client”的約定。這些文檔還充當 RSC 兼容實現應支持的規范。
最大的變化就是引入了 async / await? 作為從服務端組件獲取數據的主要方式。 除此之外,還計劃通過引入一個名為 ??use?
?? 的新 Hook 來支持從客戶端加載數據,該 Hook 用于解包 Promises。雖然不能在僅客戶端應用的任意組件中支持 ??async / await?
?,但計劃在構建僅客戶端應用時添加對它的支持,類似于 RSC 應用的結構。
現在已經解決了數據獲取的問題,并正在探索另一個方向:將數據從客戶端發送到服務器,以便可以執行數據庫突變和實現表單。通過讓跨服務端/客戶端邊界傳遞服務端操作(Server Action)函數來實現這一點,然后客戶端可以調用這些函數,從而提供無縫的 RPC。Server Actions 還在 JavaScript 加載之前提供逐步增強的表單。
React 服務端組件已經在 Next.js 應用路由中發布。這展示了一個真正將 RSC 視為原語的路由的深度集成,但這并不是構建與 RSC 兼容的路由和框架的唯一方法。RSC 規范和實現提供的特性有明顯的區別。React 服務端組件是指跨兼容React框架工作的組件規范。
React 團隊通常建議使用現有框架,但如果需要構建自己的自定義框架,也是可以的。構建自己的 RSC 兼容框架并不容易,因為需要深度構建工具集成。當前一代的構建工具非常適合在客戶端上使用,但它們在設計時并沒有為在服務端和客戶端之間拆分單個模塊圖提供一流的支持。這就是為什么 React 團隊現在直接與構建工具開發人員合作以獲得內置的 RSC。
資源加載
Suspense 允許指定在組件的數據或代碼仍在加載時在屏幕上顯示什么內容。這使用戶可以在頁面加載時以及加載更多數據和代碼的路由導航期間逐步看到更多內容。但是,從用戶的角度來看,在考慮新內容是否準備就緒時,數據加載和渲染并不能說明全部。默認情況下,瀏覽器獨立加載樣式表、字體和圖像,這可能導致 UI 跳轉和連續的布局轉換。
React 團隊正在努力將 Suspense 與樣式表、字體和圖像的加載生命周期完全集成,以便 React 將它們考慮在內,以確定內容是否已準備好顯示。在不改變編寫 React 組件的方式的情況下,更新將以更加連貫的方式進行。作為一種優化。,還將提供一種手動方式來直接從組件中預加載字體等資源。
文檔元數據
應用中的不同頁面可能具有不同的元數據,例如 <title> 標簽、description 和其他特定于此頁面的 <meta> 標簽。從維護的角度來看,將此信息放在該頁面的 React 組件中會更具可擴展性。但是,此元數據的 HTML 標簽需要位于文檔的 <head> 中,該文檔通常在應用的最根組件中。
現在有兩種方法可以解決這個問題:
- 渲染一個特殊的第三方組件,該組件將 <title>、<meta> 和其中的其他標簽移動到文檔的 <head> 中。這適用于主流瀏覽器,但有許多客戶端不運行客戶端 JavaScript,例如 Open Graph 解析器,因此該技術并不普遍適用。
- 將頁面分為兩部分進行服務端渲染。首先,渲染主要內容并收集所有此類標簽。然后使用這些標簽渲染 <head> 。最后,<head> 和主要內容被發送到瀏覽端。這種方法是可行的,但這樣就不能使用 React 18 中的流式服務端渲染了,因為必須等待所有內容渲染完畢才能發送 <head>。
這就是為什么 React 要 在組件樹中的任何位置添加內置支持來渲染 <title>、<meta>? 和元數據 <link> 標簽。它在所有環境中都以相同的方式工作,包括完全的客戶端代碼、SSR,以及未來的 RSC。
React 優化編譯器
?React 團隊一直在積極迭代 React Forget 的設計,這是一個針對 React 的優化編譯器。之前曾將其稱為“自動記憶編譯器”,這在某種意義上是正確的。但是構建編譯器幫助 React 團隊更深入地理解了 React 的編程模型。理解 React Forget 的更好方法是將其作為一個自動響應式編譯器。
React 的核心思想是開發人員將 UI 定義為當前狀態的函數。使用普通的 JavaScript 值:數字、字符串、數組、對象,并使用標準的 JavaScript 語法:if/else、for 等描述組件邏輯。心智模型是 React 將在應用狀態更改時重新渲染。這種簡單的心智模型和與 JavaScript 語義保持接近是 React 編程模型中的一個重要原則。
問題是 React 有時會響應過度:它會重新渲染太多。例如,在 JavaScript 中沒有直接的方法來比較兩個對象或數組是否相等(具有相同的鍵和值),因此在每次渲染時創建一個新的對象或數組可能會導致 React 執行比它嚴格需要的更多的工作。這意味著開發人員必須明確記憶組件,以免對更改響應過度。
React Forget 的目標是確保 React 應用在默認情況下具有適量的響應:應用僅在狀態值發生有意義的變化時才重新渲染。從實現的角度來看,這意味著自動記憶,但 React 團隊認為響應式框架是理解 React 和 Forget 的更好方式。React 目前會在對象標識更改時重新渲染。有了 Forget,React 會在語義值發生變化時才重新渲染——但不會產生深度比較的運行時成本。
進展而言,自上次更新以來,React 團隊對編譯器的設計進行了大量迭代,以與這種自動響應式方法保持一致,并納入內部使用編譯器的反饋。在去年年底開始對編譯器進行一些重大重構之后,現在已經開始在 Meta 部分生產中使用編譯器。一旦在生產中證明了它的價值,就計劃將其開源。?
離屏渲染
離屏渲染是 React 即將推出的一項功能,用于在后臺渲染屏幕而無需額外的性能開銷。可以將其視為 CSS 屬性 ??content-visibility?
? 的一個版本,它不僅適用于 DOM 元素,也適用于 React 組件。在研究過程中,發現了各種用例:
- 路由可以在后臺預渲染頁面,以便當用戶導航到該頁面時,頁面立即可用;
- 選項卡切換組件可以保留隱藏選項卡的狀態,因此用戶可以在它們之間切換而不會丟失進度。
- 虛擬列表組件可以在可見窗口上方和下方預渲染額外的行。
- 打開模態框或彈出窗口時,可以將應用的其余部分置于“后臺”模式,以便除模式之外的所有內容都禁用事件和更新。
大多數 React 開發人員不會直接與 React 屏幕外的 API 交互。相反,離屏渲染將被集成到路由和 UI 庫中,使用這些庫的開發人員將自動受益,而無需額外的工作。
這個功能可以讓我們在不改變編寫組件的方式的情況下在屏幕外渲染任何 React 樹。當一個組件在屏幕外渲染時,它實際上并沒有掛載,直到組件可見——它的 effect 不會被觸發。離屏渲染的一個關鍵特性就是可以在不丟失其狀態的情況下切換組件的可見性。
自上次更新以來,React 團隊在 Android 和 iOS 上的 React Native 應用中測試了 Meta 內部預渲染的實驗版本,并取得了積極的性能結果。除此之外,還改進了離屏渲染與 Suspense 的工作方式——在離屏樹內暫停不會觸發 Suspense 回退。剩下的工作就涉及完成向庫開發人員公開的原語。希望在今年晚些時候發布一個 RFC,以及一個用于測試和反饋的實驗性 API。
Transition Tracing
Transition Tracing API 可以檢測 React Transitions 何時變慢并調查它們變慢的原因。在上次更新后,React 團隊完成了 API 的初始設計并發布了 RFC,基本能力也已經實現,該項目目前處于擱置狀態。歡迎對 RFC 進行反饋,并期待恢復其開發,為 React 提供更好的性能測量工具。這對于構建在基于 React Transitions 的路由特別有用,比如 Next.js 應用路由。
參考:https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023