2022 年,React 團(tuán)隊(duì)在做什么?
上個(gè)月中,React 團(tuán)隊(duì)發(fā)了一篇文章 React Labs: What We've Been Working On – June 2022 講了一下最近他們?cè)谧龅氖虑?,社區(qū)沒(méi)有看到中文翻譯,這里簡(jiǎn)單解讀下原文,我發(fā)現(xiàn)如果不常浸泡在技術(shù)英文的語(yǔ)境里,有些句子還挺難懂的。
原文鏈接: https://reactjs.org/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022.html
2022 年 6 月 15 日,作者:Andrew Clark、Dan Abramov、Jan Kassens、Joseph Savona、Josh Story、Lauren Tan、Luna Ruan、Mengdi Chen、Rick Hanlon、Robert Zhang、Sathya Gunasekaran、Sebastian Markb?ge和 黃玄 。
React 18已經(jīng)醞釀多年,它為 React 團(tuán)隊(duì)帶來(lái)了寶貴的經(jīng)驗(yàn)。它的發(fā)布是多年研究和探索多種途徑的結(jié)果。其中一些路徑是成功的;更多的是導(dǎo)致新見(jiàn)解的死胡同。我們學(xué)到的一個(gè)教訓(xùn)是,社區(qū)等待新功能卻沒(méi)有深入了解我們正在探索的這些路徑是令人沮喪的。
我們通常在任何時(shí)候都有許多項(xiàng)目正在進(jìn)行,從更具實(shí)驗(yàn)性的到明確定義的。展望未來(lái),我們希望開(kāi)始定期分享更多關(guān)于我們?cè)谶@些項(xiàng)目中與社區(qū)合作的內(nèi)容。
為了設(shè)定期望,這不是一個(gè)有明確時(shí)間表的路線圖。其中許多項(xiàng)目正在積極研究中,很難確定具體的發(fā)布日期。根據(jù)我們目前的評(píng)估,應(yīng)該不會(huì)在當(dāng)前的迭代中發(fā)布。相反,我們想與您分享我們正在積極思考哪些問(wèn)題,以及我們迄今為止有所認(rèn)識(shí)的東西。
解讀:這個(gè)開(kāi)場(chǎng)白,解答了為什么外界總覺(jué)得 React 的更新太慢了。不是 React 團(tuán)隊(duì)不干事,是做了很多探索性的工作,有些沒(méi)啥結(jié)果,沒(méi)有對(duì)外說(shuō)而已,其實(shí)忙的很。按照我的理解,像 React 這種前端基礎(chǔ)設(shè)施,變化太快不見(jiàn)得是一件好事,比如 React-Router 變化快,兼容性也差,當(dāng)然還有 AngularJS。React 的 API 算是延續(xù)性非常好的了,而且相當(dāng)穩(wěn)定。
服務(wù)器組件 Server Components
我們于 2020 年 12 月宣布了 React 服務(wù)器組件 (RSC) 的實(shí)驗(yàn)性方案(https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html)。
從那時(shí)起,我們一直在 React 18 支持的部分,并致力于根據(jù)實(shí)驗(yàn)反饋進(jìn)行改進(jìn)。
特別是,我們放棄了使用 fork I/O libraries(例如 react-fetch)的想法,而是采用 async/await 模型以獲得更好的兼容性。這在技術(shù)上并不會(huì) block RSC 的發(fā)布,因?yàn)槟€可以使用 routers 來(lái)獲取數(shù)據(jù)。另一個(gè)變化是我們已經(jīng)不用文件擴(kuò)展名這種方式,轉(zhuǎn)而支持 注釋邊界(annotating boundaries)。
我們正在與 Vercel (一個(gè)網(wǎng)站托管平臺(tái))和 Shopify 合作,統(tǒng)一捆綁程序(unify bundler)對(duì) Webpack 和 Vite 中共享語(yǔ)義(shared semantics)的支持。在發(fā)布之前,我們希望確保 RSC 的語(yǔ)義在整個(gè) React 生態(tài)系統(tǒng)中是相同的。這是達(dá)到穩(wěn)定的主要障礙。
解讀:React Server Component 對(duì)我來(lái)說(shuō)是比較陌生的,我平時(shí)也沒(méi)有使用過(guò)。看 React 團(tuán)隊(duì)的意思,也不希望我們用這種底層特性,而是讓 Vercel、Shopify、webpack、 Vite 這些周邊生態(tài)的庫(kù)來(lái)支持,我們直接用這個(gè)庫(kù)就好了。
資產(chǎn)加載 Asset Loading
目前,腳本、外部樣式、字體和圖像等資產(chǎn)通常是使用外部系統(tǒng)預(yù)加載和加載的。這會(huì)使跨新環(huán)境(如流、服務(wù)器組件等)進(jìn)行協(xié)調(diào)變得很棘手。我們正在考慮通過(guò)適用于所有 React 環(huán)境的 React API 添加 API 以預(yù)加載和加載去重的外部資產(chǎn)。
我們也在考慮讓這些支持 Suspense,這樣您就可以讓圖像、CSS 和字體在加載之前阻止顯示,但不會(huì)阻止流式傳輸和并發(fā)渲染。這有助于避免在視覺(jué)效果和布局發(fā)生變化時(shí)出現(xiàn)“爆米花” (popcorning)。
解讀:這里解釋下“爆米花”這個(gè)詞,大家開(kāi)發(fā)的時(shí)候應(yīng)該經(jīng)??吹揭粋€(gè)頁(yè)面在數(shù)據(jù)加載完成前后,所占的空間大小是差距是非常大的,這就導(dǎo)致頁(yè)面瞬間有個(gè)爆炸的效果。尤其是頁(yè)面上圖片較多的時(shí)候。React 團(tuán)隊(duì)正在開(kāi)發(fā)一個(gè)通用的請(qǐng)求外部資源的 API,來(lái)解決這個(gè)問(wèn)題。這塊還是挺期待的,希望能早點(diǎn)體驗(yàn)下。
靜態(tài)服務(wù)器渲染優(yōu)化 Static Server Rendering Optimizations
靜態(tài)站點(diǎn)生成 (SSG) 和增量靜態(tài)重新生成 (ISR) 是獲得可緩存頁(yè)面性能的好方法,但我們認(rèn)為我們可以添加功能來(lái)提高動(dòng)態(tài)服務(wù)器端渲染 (SSR) 的性能 - 特別是當(dāng)大多數(shù)但不是全部?jī)?nèi)容是可緩存的。我們正在探索利用編譯和靜態(tài)通道優(yōu)化服務(wù)器渲染的方法。
解讀:服務(wù)端渲染,我了解的不多,這個(gè)應(yīng)該是一些性能的優(yōu)化。
React 優(yōu)化編譯器 React Optimizing Compiler
我們?cè)?React Conf 2021 上對(duì) React Forget 進(jìn)行了 預(yù)告useMemo。它是一個(gè)編譯器,可以自動(dòng)生成等價(jià)的和useCallback調(diào)用以最小化重新渲染的成本,同時(shí)保留 React 的編程模型。
最近,我們完成了對(duì)編譯器的重寫,使其更加可靠和強(qiáng)大。這種新架構(gòu)使我們能夠分析和記憶更復(fù)雜的模式,例如使用局部突變,并開(kāi)辟了許多新的編譯時(shí)優(yōu)化機(jī)會(huì),而不僅僅是與緩存掛鉤。
我們還在開(kāi)發(fā)一個(gè)用于探索編譯器許多方面的 Playground 。雖然 Playground 的目標(biāo)是使編譯器的開(kāi)發(fā)更容易,但我們認(rèn)為它將更容易嘗試并為編譯器的功能建立直覺(jué)。它揭示了它如何在后臺(tái)工作的各種見(jiàn)解,并在您鍵入時(shí)實(shí)時(shí)呈現(xiàn)編譯器的輸出。這將在發(fā)布時(shí)與編譯器一起提供。
解讀:從去年底,黃玄介紹了 React Forget ,可以通過(guò)編譯時(shí)優(yōu)化 React 代碼的性能。半年過(guò)去了,中間做了很多事情,主要是兩件事,一是對(duì)編譯器本身的開(kāi)發(fā),另一個(gè)是 Playground 的開(kāi)發(fā)。Playground 的意思是游樂(lè)場(chǎng),其實(shí)就是可以在線上修改代碼并看到運(yùn)行結(jié)果的一個(gè)工具。
離屏 Offscreen
今天,如果你想隱藏和顯示一個(gè)組件,你有兩個(gè)選擇。一種是從樹(shù)中完全添加或刪除它。這種方法的問(wèn)題在于,每次卸載時(shí) UI 的狀態(tài)都會(huì)丟失,包括存儲(chǔ)在 DOM 中的狀態(tài),例如滾動(dòng)位置。
另一種選擇是保持組件安裝并使用 CSS 直觀地切換外觀。這會(huì)保留 UI 的狀態(tài),但會(huì)以性能為代價(jià),因?yàn)?React 必須在收到新更新時(shí)不斷渲染隱藏組件及其所有子組件。
Offscreen 引入了第三種選擇:在視覺(jué)上隱藏 UI,但降低其內(nèi)容的優(yōu)先級(jí)。這個(gè)想法在本質(zhì)上類似于 content-visibility CSS 屬性:當(dāng)內(nèi)容被隱藏時(shí),它不需要與 UI 的其余部分保持同步。React 可以推遲渲染工作,直到應(yīng)用程序的其余部分空閑,或者直到內(nèi)容再次可見(jiàn)。
Offscreen 只是一個(gè)小技巧,他的目的是解鎖更高級(jí)的功能。與 React 的其他并發(fā)特性類似 startTransition,在大多數(shù)情況下,您不會(huì)直接與 Offscreen API 交互,而是通過(guò)一個(gè)完善的框架來(lái)實(shí)現(xiàn)以下模式:
即時(shí)過(guò)渡( Instant transitions ):一些路由框架已經(jīng)預(yù)取數(shù)據(jù)以加速后續(xù)導(dǎo)航,例如懸停在鏈接上時(shí)。使用 Offscreen,他們還可以在后臺(tái)預(yù)渲染下一個(gè)屏幕。
可重用狀態(tài)( Reusable state ):同樣,在路線或選項(xiàng)卡之間導(dǎo)航時(shí),您可以使用 Offscreen 來(lái)保留前一個(gè)屏幕的狀態(tài),以便您可以切換回來(lái)并從中斷處繼續(xù)。
虛擬化列表渲染( Virtualized list rendering ):顯示大型項(xiàng)目列表時(shí),虛擬化列表框架將預(yù)呈現(xiàn)比當(dāng)前可見(jiàn)的更多行。您可以使用 Offscreen 以低于列表中可見(jiàn)項(xiàng)目的優(yōu)先級(jí)預(yù)呈現(xiàn)隱藏行。
背景內(nèi)容( Backgrounded content ):我們還在探索一項(xiàng)相關(guān)功能,用于在不隱藏背景的情況下降低內(nèi)容的優(yōu)先級(jí),例如在顯示模式疊加層時(shí)。
解讀:這個(gè) Offscreen 可是太有用了,通過(guò)這個(gè)新的 API ,我們可以控制組件的顯示和隱藏,但不同于 {isShow && }和 <div style={{ display: isShow ? 'block':'none' }} 這兩種方式,他是類似 CSS 的 content-visibility 的屬性,Chromium 85 開(kāi)始有了 content-visibility 屬性,這可能是對(duì)于提升頁(yè)面加載性能提升最有效的CSS屬性,content-visibility 讓用戶代理正常情況下跳過(guò)元素渲染工作(包括 layout 和 painting ),除非需要的時(shí)候進(jìn)行渲染工作。
如果頁(yè)面有大量離屏(off-screen)的內(nèi)容,借助 content-visibility 屬性可以跳過(guò)離屏內(nèi)容的渲染,加快用戶首屏渲染時(shí)間,可以做到減少的頁(yè)面可交互的等待時(shí)間。React 后面要提供的這個(gè) API,也不希望開(kāi)發(fā)者直接使用,而是通過(guò)使用像 React-Router 這種庫(kù)來(lái)實(shí)現(xiàn),或許不久以后我們就有類似 Vue 里的 Keep-Alive 的功能可用了。
過(guò)渡跟蹤 Transition Tracing
目前,React 有兩個(gè)分析工具。Original Profiler顯示了分析會(huì)話中所有提交的概覽。對(duì)于每次提交,它還顯示所有渲染的組件以及渲染它們所花費(fèi)的時(shí)間。我們還有一個(gè)在 React 18 中引入的 Timeline Profiler的 beta 版本,它顯示組件何時(shí)安排更新以及 React 何時(shí)處理這些更新。這兩個(gè)分析器都可以幫助開(kāi)發(fā)人員識(shí)別代碼中的性能問(wèn)題。
我們已經(jīng)意識(shí)到,開(kāi)發(fā)人員并沒(méi)有發(fā)現(xiàn)了解單個(gè)緩慢提交或脫離上下文的組件是很有用的。了解導(dǎo)致緩慢提交的真正原因會(huì)更有用。并且開(kāi)發(fā)人員希望能夠跟蹤特定的交互(例如按鈕單擊、初始加載或頁(yè)面導(dǎo)航)以觀察性能回歸并了解交互緩慢的原因以及如何修復(fù)它。
我們之前嘗試通過(guò)創(chuàng)建交互跟蹤 API來(lái)解決這個(gè)問(wèn)題,但它存在一些基本的設(shè)計(jì)缺陷,降低了跟蹤交互為何緩慢的準(zhǔn)確性,有時(shí)會(huì)導(dǎo)致交互永無(wú)止境。由于這些問(wèn)題,我們最終刪除了這個(gè) API 。
我們正在開(kāi)發(fā)一個(gè)新版本的交互跟蹤 API(暫時(shí)稱為轉(zhuǎn)換跟蹤,因?yàn)樗峭ㄟ^(guò) 啟動(dòng)的startTransition)來(lái)解決這些問(wèn)題。
解讀:React 的性能分析工具很好用,后面還會(huì)新增一種時(shí)間線的分析工具,Time Profiler ,來(lái)分析并發(fā)更新時(shí)的調(diào)度情況。它可以做到當(dāng)發(fā)現(xiàn)某次更新比較緩慢時(shí),可以跟蹤這次交互的完整過(guò)程,分析性能瓶頸。
新的 React 文檔 New React Docs
去年,我們宣布了新的 React 文檔網(wǎng)站的 beta 版本。新的學(xué)習(xí)材料首先教授 Hooks,并有新的圖表、插圖以及許多交互式示例和挑戰(zhàn)。之前我們暫停了這項(xiàng)工作,因?yàn)橐獙W⒂?React 18 版本的開(kāi)發(fā),但現(xiàn)在 React 18 已經(jīng)發(fā)布,我們正在積極努力完成和發(fā)布新文檔。
我們目前正在寫一個(gè)關(guān)于 effects 的詳細(xì)部分,因?yàn)槲覀兟?tīng)說(shuō)對(duì)于新的和有經(jīng)驗(yàn)的 React 用戶來(lái)說(shuō),這都是更具挑戰(zhàn)性的主題之一。Synchronizing with Effects是該系列中的第一篇文章,接下來(lái)幾周還會(huì)發(fā)布更多內(nèi)容。當(dāng)我們第一次開(kāi)始編寫有關(guān) effects 的詳細(xì)部分時(shí),我們已經(jīng)意識(shí)到可以通過(guò)向 React 添加新的原始 API 來(lái)簡(jiǎn)化許多常見(jiàn)的 effects 模式。我們?cè)?useEvent RFC中分享了一些初步想法。它目前處于早期研究階段,我們?nèi)栽诘@個(gè)想法。我們感謝社區(qū)迄今為止對(duì) RFC 的評(píng)論,以及對(duì)正在進(jìn)行的文檔重寫的反饋和貢獻(xiàn)。我們要特別感謝 Harish Kumar(在一家印度金融科技公司工作的印度小哥)提交并審查了對(duì)新網(wǎng)站實(shí)施的許多改進(jìn)。
解讀:新的 React 文章還是有很多變化,他從 2020年10月開(kāi)始寫的,老文檔的問(wèn)題是原來(lái)的文檔是以 Class Component 為主線的,但是新的 React 設(shè)計(jì)思路和發(fā)展已經(jīng)跟之前有了較大的變化,開(kāi)發(fā)者如果還是按照之前的設(shè)計(jì)思想來(lái)理解 React ,就不能快速的獲得 React 的真諦,而且目前 Hooks 已經(jīng)成為 React 最重要的部分,但老的文檔里對(duì)這部分的介紹優(yōu)先級(jí)比較低,所以新的文檔有以下幾個(gè)變化:
- 以 HOOKS 為主線,串起所有 React 的相關(guān)知識(shí),尤其是性能優(yōu)化部分。
- 介紹 React 新的設(shè)計(jì)模式,思路和哲學(xué)。
- 增強(qiáng)了互動(dòng)學(xué)習(xí)的部分,開(kāi)發(fā)者可以在網(wǎng)站上互動(dòng)的查看示例,和更有意思的 challengesa 幫助你更好的學(xué)習(xí)。
- 暗夜模式,可以切換黑夜和白天,對(duì)于熬夜黨很友好。
新的文檔到現(xiàn)在已經(jīng) 1 年多了,很多吐槽一個(gè)文檔都要寫這么久,其實(shí)大家細(xì)心看這個(gè)文檔,就會(huì)發(fā)現(xiàn)是非??季康?,就像一本教科書,極力用通俗的語(yǔ)言把知識(shí)點(diǎn)說(shuō)明白。這也是 Dan 和 Rachel 的強(qiáng)項(xiàng)。