SolidJS 一直以來以其精細反應式反應模型(Fine-grained Reactivity)聞名,它完全捨棄了 React 所使用的虛擬 DOM(Virtual DOM),直接將狀態更新對應到實際的 DOM 節點,因此擁有極高的執行效能。在最新的 2.0 Beta 版本中,SolidJS 針對非同步處理、Suspense 機制以及更新排程進行了深層的底層重構,旨在解決開發者在處理非同步數據時常遇到的複雜狀態管理問題。
非同步處理的一等公民化
在前端開發中,非同步操作(Async)通常被視為副作用,需要透過額外的狀態變數(如 isLoading)或複雜的 Promise 鏈結來管理。SolidJS 2.0 將非同步處理提升為一等公民(First-class Async),這意味著框架的反應式圖譜(Reactive Graph)現在能直接處理 Promise。
具體來說,開發者現在可以直接將 Promise 傳入 createMemo 等計算函數中,框架會自動處理暫停(Suspension)與恢復(Resumption)的過程。這大幅簡化了以往需要手動協調的非同步邏輯,讓非同步數據的流向變得像同步數據一樣自然。
Suspense 與 Pending 狀態的重新定義
過去的 Suspense 機制在數據更新時,經常會導致整個 UI 樹被拆除並重新渲染,造成視覺上的閃爍或跳轉感。SolidJS 2.0 重新設計了 Loading 與 Pending 的區分。
現在的 Loading 僅用於處理初始載入,即組件第一次準備就緒前顯示回退界面(Fallback)。而後續的數據更新則透過 isPending 函數來表達。這種設計確保了 UI 的穩定性,避免在數據刷新時將整個界面撕裂,提升了使用者體驗。
樂觀更新與 Action 原語
為了優化伺服器端數據交互,2.0 引入了 action 函數與 createOptimisticStore。這套組合允許開發者將伺服器寫入、樂觀更新(Optimistic Updates,指在伺服器回應前先假設成功並更新 UI)以及數據重新驗證(Revalidation)整合在單一且連貫的流程中,減少了手動同步本地狀態與遠端狀態的心智負擔。
確定性批處理與微任務排程
在反應式系統中,更新的觸發順序至關重要。SolidJS 2.0 引入了確定性的批處理(Deterministic Batching)。現在所有的更新會被放入微任務(Microtask)中排程,讀取操作僅在 flush 呼叫之後才會更新。
雖然這改變了 1.x 版本中寫入後立即讀取就能拿到新值的直覺模式,但作者 Ryan Carniato 指出,這是為了實現一致性非同步處理所必須付出的代價。透過建立明確的邊界,框架能吸收掉底層的複雜度,避免在複雜的非同步鏈結中出現狀態不一致的 race condition。
重大變更與開發者適應
此次更新包含多項破壞性變更(Breaking Changes)。例如 Index 組件被 <For keyed={false}> 取代,createEffect 被拆分為計算(Compute)與應用(Apply)兩個階段,而 onMount 則由 onSettled 取代。
部分開發者對於 createEffect 的拆分以及更新後需 flush 才能讀取新值感到不適,認為這增加了開發複雜度。然而,官方的觀點是,若正確使用新的設計模式,開發者將發現自己幾乎不再需要頻繁使用 createEffect,因為大部分的邏輯都能透過更簡潔的反應式原語來達成。
總結
SolidJS 2.0 Beta 不僅僅是 API 的更迭,而是一次對非同步反應式系統的重新思考。它試圖在保持極致效能的同時,提供一套能優雅處理非同步數據流的標準方案。對於追求高效能且希望擺脫虛擬 DOM 負擔的工程師來說,這是一個值得關注的演進。
來源:infoq.com
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。