以后沒有 React Concurrent Mode了
大家好,我卡頌。
相信很多關注React的朋友都知道Concurrent Mode,他是React漸進升級策略的產物。
即然是策略,那就有可能調整,這不,根據What happened to concurrent mode?[1],在v18中將不會有Concurrent Mode了。
本文讓我們一起了解React漸進升級策略的演進過程。
React新老架構的區別
可以認為采用Fiber架構前的React只支持一種優先級:同步優先級,即所有更新是“同步、不可中斷”的形式。
采用Fiber架構后的React支持包括同步優先級在內的多種優先級,或者說新架構支持并發更新。
所以新架構可以模擬老架構的運行機制(即不開啟并發更新)。
當新架構開啟并發更新后,就能使用React為了解決CPU的瓶頸、IO的瓶頸而設計的并發特性(Concurrent Feature),比如:
- useDeferredValue
- useTransition
- 全功能的Suspense
React所有版本可能的情況
當前所有React版本一定屬于如下情況之一:
- v15及之前的老架構
- v16之后的新架構,未開啟并發更新,與情況1行為一致
- v16之后的新架構,未開啟并發更新,但是啟用了一些新功能(比如Automatic Batching)
- v16之后的新架構,開啟并發更新
v16、v17默認屬于情況2。
之所以劃分多種情況,是因為情況4的React一些行為異于情況1、2、3(比如部分以componentWill開頭的生命周期函數的調用時機發生變化),也就是說開啟并發更新可能造成老代碼不兼容。
為了讓廣大開發者能夠平滑過渡,React團隊采用了「漸進升級」方案。
早期的漸進升級策略
v16.3新增了StrictMode,對開發者編寫的「不符合并發更新規范的代碼」作出提示,逐步引導開發者寫出規范代碼。
此時React團隊的「漸進升級」策略是:讓頁面中可以同時存在三種模式的應用,具體如下:
- Legacy模式,通過ReactDOM.render(
, rootNode)創建的應用遵循該模式。默認關閉StrictMode,表現同情況2 - Blocking模式,通過ReactDOM.createBlockingRoot(rootNode).render(
)創建的應用遵循該模式,作為從Legacy向Concurrent過渡的中間模式,默認開啟StrictMode,表現同情況3 - Concurrent模式,通過ReactDOM.createRoot(rootNode).render(
)創建的應用遵循該模式,默認開啟StrictMode,表現同情況4
三種模式可用特性對比
在v17之前,大多數事件會冒泡到HTML元素,為了讓同一個頁面下不同應用獨立,v17之后事件會冒泡到應用所在根元素。
所以v17也被稱為「墊腳石」版本,他是為「開啟并發更新」做鋪墊的版本。
當前的漸進升級策略
但是,根據社區的反饋,React團隊意識到當前的「漸進升級」策略存在問題。
這三種模式影響的是整個應用,從Legacy升級到Blocking后,由于開啟StrictMode,整個應用的「并發不兼容警告」都會上報。從這個角度看,并沒有起到「漸進升級」的目的。
另一方面,開發者從新架構中獲益更多是由于使用了并發特性,即然新架構支持「開關并發更新」,完全可以在使用了并發特性后再開啟并發更新。這樣就只需在「使用了并發特性的組件」部分啟用StrictMode。
相比劃分三種模式,這種以「是否使用并發特性」作為是否開啟并發更新的依據,更符合「漸進升級」中「漸進」的理念。
所以在v18中,不再有三種模式,統一使用ReactDOM.createRoot(rootNode).render(
總結
一句話總結:v18以后只會有并發特性,不會有并發模式。
作為一個發展了8年之久的前端框架,要想推進社區完成帶有breaking change的迭代升級,注定是困難的。
我們也看到了React團隊在此確實付出很多心血。
想問問各位,還學得動么?
參考資料
[1]What happened to concurrent mode?:
https://github.com/reactwg/react-18/discussions/64