React Labs:我們正在進行的工作 - 2024 年 2 月
2024 年 2 月 15 日,由 Joseph Savona、Ricky Hanlon、Andrew Clark、Matt Carroll 和 Dan Abramov 發表。
在 React Labs 的文章中,我們會撰寫關於積極研發中的專案。自從我們上次更新以來,我們已經取得了顯著的進展,並且我們想要分享我們的進度。
React 編譯器
React 編譯器不再是一個研究專案:該編譯器現在已在 instagram.com 的生產環境中使用,我們正致力於將編譯器發布到 Meta 的其他平台,並準備第一個開源版本。
正如我們在上一篇文章中所討論的,當狀態改變時,React *有時* 會重新渲染過多內容。自 React 誕生以來,我們針對這種情況的解決方案一直是手動記憶體化。在我們目前的 API 中,這意味著應用 useMemo
、useCallback
和 memo
API 來手動調整 React 在狀態改變時重新渲染的程度。但手動記憶體化是一種妥協。它會使我們的程式碼變得雜亂,容易出錯,並且需要額外的工作來保持更新。
手動記憶體化是一個合理的妥協方案,但我們並不滿足。我們的願景是讓 React 在狀態改變時*自動*重新渲染 UI 的正確部分,*而不會犧牲 React 的核心心智模型*。我們相信 React 的方法——UI 作為狀態的簡單函數,使用標準的 JavaScript 值和慣用法——是 React 對許多開發人員來說易於理解的關鍵原因。這就是為什麼我們投資於構建 React 優化編譯器的原因。
由於其鬆散的規則和動態特性,JavaScript 是一種眾所周知難以優化的語言。React 編譯器能夠通過同時模擬 JavaScript 的*規則*和“React 的規則”來安全地編譯程式碼。例如,React 元件必須是冪等的——給定相同的輸入返回相同的值——並且不能改變 props 或狀態值。這些規則限制了開發人員可以做的事情,並幫助劃分出一個安全的空間供編譯器優化。
當然,我們理解開發人員有時會稍微違反規則,我們的目標是讓 React 編譯器在盡可能多的程式碼上開箱即用。編譯器會嘗試檢測程式碼是否沒有嚴格遵循 React 的規則,並會在安全的地方編譯程式碼,或者在不安全的地方跳過編譯。我們正在針對 Meta 龐大且多樣的程式碼庫進行測試,以幫助驗證這種方法。
對於那些好奇如何確保他們的程式碼遵循 React 規則的開發人員,我們建議啟用嚴格模式並設定 React 的 ESLint 插件。這些工具可以幫助您捕捉 React 程式碼中的細微錯誤,從而提高您應用程式的品質,並使您的應用程式適用於未來的功能,例如 React 編譯器。我們也正在編寫 React 規則的整合文件,並更新我們的 ESLint 插件,以幫助團隊理解和應用這些規則來建立更強大的應用程式。
要查看編譯器的實際應用,您可以查看我們去年秋天的演講。在演講時,我們有嘗試在 instagram.com 的一個頁面上使用 React 編譯器的早期實驗數據。從那時起,我們已將編譯器發布到 instagram.com 的整個生產環境中。我們還擴大了團隊規模,以加速向 Meta 的其他平台推出並開源。我們對未來的發展感到興奮,並將在未來幾個月內分享更多資訊。
動作
我們先前分享了我們正在探索使用伺服器動作將資料從客戶端發送到伺服器的解決方案,以便您可以執行資料庫異動和實作表單。在伺服器動作的開發過程中,我們擴展了這些 API,以支援僅限客戶端應用程式中的資料處理。
我們將這一系列更廣泛的功能簡稱為“動作”。動作允許您將函數傳遞給 DOM 元素,例如 <form/>
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
action
函數可以同步或非同步操作。您可以使用標準 JavaScript 在客戶端定義它們,或使用 'use server'
指令在伺服器上定義它們。當使用動作時,React 將會為您管理資料提交的生命週期,並提供 useFormStatus
和 useActionState
等鉤子來存取表單動作的目前狀態和回應。
預設情況下,Actions 會在 transition 中提交,讓目前的頁面在操作處理時保持互動性。由於 Actions 支援非同步函式,我們也新增了在 transitions 中使用 async/await
的能力。這讓您可以在非同步請求(例如 fetch
)開始時,使用 transition 的 isPending
狀態來顯示載入中的 UI,並在套用更新的整個過程中持續顯示載入中的 UI。
除了 Actions 之外,我們還推出了一個名為 useOptimistic
的功能,用於管理樂觀狀態更新。透過這個 hook,您可以套用臨時更新,這些更新會在最終狀態提交後自動還原。對於 Actions 來說,這讓您可以在用戶端樂觀地設定資料的最終狀態(假設提交成功),並在伺服器傳回資料後還原到該值。它使用一般的 async
/await
,因此無論您是在用戶端使用 fetch
,還是在伺服器使用 Server Action,其運作方式都相同。
函式庫作者可以使用 useTransition
在他們自己的元件中實作自定義的 action={fn}
props。我們的目的是讓函式庫在設計其元件 API 時採用 Actions 模式,為 React 開發者提供一致的體驗。例如,如果您的函式庫提供了一個 <Calendar onSelect={eventHandler}>
元件,請考慮也公開一個 <Calendar selectAction={action}>
API。
雖然我們最初專注於用於用戶端-伺服器資料傳輸的 Server Actions,但我們 React 的理念是在所有平台和環境中提供相同的程式設計模型。如果可能,如果我們在用戶端引入一個功能,我們的目標是讓它也能在伺服器上運作,反之亦然。這種理念讓我們能夠建立一套可在任何地方運作的 API,讓您以後更容易升級到不同的環境。
Actions 現已在 Canary 頻道中提供,並將在 React 的下一個版本中發布。
React Canary 的新功能
我們推出了 React Canaries,讓您可以選擇在個別新的穩定功能設計接近完成時立即採用,不必等到它們在穩定語意化版本中發布。
Canaries 改變了我們開發 React 的方式。以前,功能會在 Meta 內部私下研究和構建,因此使用者只會在發布到穩定版時看到最終的成品。有了 Canaries,我們可以在社群的幫助下公開構建,以完成我們在 React Labs 部落格系列中分享的功能。這表示您會更早聽到新功能的消息,因為它們正在最後定案,而不是在完成之後。
React Server Components、資源載入、文件元資料和 Actions 都已進入 React Canary,我們已在 react.dev 上新增了這些功能的文件。
-
指示詞 (Directives):
"use client"
和"use server"
是為全端 React 框架設計的打包器功能。它們標記了兩個環境之間的「分割點」:"use client"
指示打包器產生一個<script>
標籤(例如 Astro Islands),而"use server"
告訴打包器產生一個 POST 端點(例如 tRPC Mutations)。它們讓您可以編寫可重複使用的元件,將用戶端互動性與相關的伺服器端邏輯組合在一起。 -
文件元資料:我們新增了內建支援,可在您的元件樹中的任何位置渲染
<title>
、<meta>
和元資料<link>
標籤。這些標籤在所有環境中的運作方式都相同,包括純用戶端程式碼、SSR 和 RSC。這為像 React Helmet 這樣的函式庫所開創的功能提供了內建支援。 -
資源載入:我們將 Suspense 與樣式表、字型和指令碼等資源的載入生命週期整合在一起,讓 React 將它們納入考量,以判斷
<style>
、<link>
和<script>
等元素中的內容是否準備好顯示。我們還新增了新的 資源載入 API,例如preload
和preinit
,以便更好地控制資源何時應該載入和初始化。 -
動作 (Actions):如同上述所分享,我們新增了動作 (Actions) 來管理從客戶端到伺服器的資料傳送。您可以將
action
屬性添加到諸如<form/>
的元素中,使用useFormStatus
讀取狀態,使用useActionState
處理結果,並使用useOptimistic
進行 UI 的樂觀更新。
由於所有這些功能協同工作,因此難以將它們單獨發佈到穩定版本通道。如果沒有用於訪問表單狀態的輔助 hooks,發佈動作 (Actions) 將會限制動作 (Actions) 的實際可用性。如果沒有整合伺服器動作 (Server Actions),引入 React 伺服器元件 (React Server Components) 將會使修改伺服器上的資料變得更加複雜。
在我們將一組功能發佈到穩定版本通道之前,我們需要確保它們能夠協同工作,並且開發人員具備在生產環境中使用它們所需的一切。React Canary 允許我們單獨開發這些功能,並逐步發佈穩定的 API,直到整個功能集完成。
React Canary 中的當前功能集已完成並準備發佈。
React 的下一個主要版本
經過幾年的迭代,react@canary
現在已準備好發佈到 react@latest
。上述新功能與您的應用程式執行的任何環境相容,提供生產環境使用所需的一切。由於資源載入和文件詮釋資料可能對某些應用程式造成重大變更,因此 React 的下一個版本將會是一個主要版本:React 19。
發佈前還有更多工作要做。在 React 19 中,我們還添加了期待已久的改進,這些改進需要重大變更,例如支援 Web Components。我們現在的重點是完成這些變更、準備發佈、完成新功能的文件,並發佈包含內容的公告。
在接下來的幾個月中,我們將分享更多關於 React 19 包含的所有內容、如何採用新的客戶端功能以及如何建構對 React 伺服器元件 (React Server Components) 的支援的資訊。
Offscreen(已重新命名為 Activity)。
自上次更新以來,我們已將正在研究的功能從「Offscreen」重新命名為「Activity」。名稱「Offscreen」意味著它僅適用於應用程式中不可見的部分,但在研究此功能時,我們意識到應用程式中的某些部分可能是可見但處於非活動狀態,例如模態視窗後面的內容。新名稱更準確地反映了將應用程式的某些部分標記為「活動」或「非活動」的行為。
Activity 仍在研究中,我們剩餘的工作是最終確定公開給函式庫開發人員的原語。在我們專注於發佈更完整的功能時,我們已將此區域的優先順序降低。
除了本次更新之外,我們的團隊還在會議上發表了演講,並在 podcast 上露面,以更詳細地介紹我們的工作並回答問題。
-
Sathya Gunasekaran 在 React India 研討會上發表了關於 React 編譯器的演講
-
Dan Abramov 在 RemixConf 上發表了題為「React from Another Dimension」的演講,探討了 React 伺服器元件 (React Server Components) 和動作 (Actions) 的另一種可能的創造歷史
-
Dan Abramov 在 Changelog 的 JS Party podcast 上接受了關於 React 伺服器元件 (React Server Components) 的採訪
-
Matt Carroll 在 Front-End Fire podcast 上接受了採訪,討論了 The Two Reacts
感謝 Lauren Tan、Sophie Alpert、Jason Bonta、Eli White 和 Sathya Gunasekaran 審閱這篇文章。
感謝您的閱讀,React Conf 見!