<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          React 并發(fā)渲染的前世今生

          共 4488字,需瀏覽 9分鐘

           ·

          2022-05-12 03:10

          2161 天!

          86c002bff0f39d8ebc7cea909648dea1.webp

          這是 React 團(tuán)隊(duì)從計(jì)劃為 React 增加 并發(fā)渲染 的能力,到 React 18 可用版本發(fā)布所花費(fèi)的時(shí)間。

          為啥中間花費(fèi)了這么長(zhǎng)的時(shí)間?中間又發(fā)生了哪些有趣的故事?我們回到 2016 年,來(lái)回顧一下 ?React 并發(fā)渲染 ?誕生的過(guò)程!

          在 React 運(yùn)行時(shí)優(yōu)化方案?的演進(jìn) 一文中,我們從技術(shù)細(xì)節(jié)和實(shí)現(xiàn)原理的角度詳細(xì)解讀了 React 并發(fā)渲染的演進(jìn)。但是技術(shù)細(xì)節(jié)太多,很多小伙伴表示讀起來(lái)比較困難,今天這篇文章會(huì)以更輕松的方式帶大家看整體的演進(jìn)之路,不會(huì)涉及太多的技術(shù)性,讀起來(lái)會(huì)更簡(jiǎn)單,相信看完這篇文章再去看之前的問(wèn)會(huì)有不一樣的理解。

          瀏覽器的瓶頸

          早在 2016 年,React 就已經(jīng)開(kāi)始在前端屆爆火了。React 團(tuán)隊(duì)始終有一個(gè)目標(biāo),就是給基于 React 而構(gòu)建的上百萬(wàn)個(gè)網(wǎng)站提供最好的性能體驗(yàn)!

          但是提升性能最大的瓶頸,不一定和 React 本身有關(guān)。而是與 React 建立在的語(yǔ)言 JavaScript,以及 ?JavaScript 所在的瀏覽器環(huán)境有關(guān)。

          54d58e00b8ee15357fe0bd6f7e7fe29c.webp

          瀏覽器會(huì)在一個(gè)主線程里處理所有的 JavaScript 代碼、用戶事件、渲染、布局、繪制以及重排。

          通常情況下,它們互不打擾,相互運(yùn)行的挺和諧的,但是如果一不小心,就有可能導(dǎo)致問(wèn)題。

          65bfca302a78445ea1d72c55d71b262a.webpReact Conf 2018

          React 現(xiàn)在是同步的,這意味著當(dāng)你更新組件時(shí),React 會(huì)同步處理這個(gè)更新, 它會(huì)在一個(gè)主線程上持續(xù)工作,直到所有更新完成。所以問(wèn)題在于,用戶事件也會(huì)在主線程上觸發(fā),如果此時(shí) React 正在渲染更新,同時(shí)用戶嘗試以同步的方式輸入一些內(nèi)容, React 會(huì)等待正在執(zhí)行的所有渲染完成后才能去處理用戶事件?!?React Conf 2018

          Fiber 誕生

          915d5cec313125e0ec6338c6cc2d8ed8.webp多線程渲染

          所以,如果問(wèn)題在于渲染阻塞了主線程,那我們不能在另外一個(gè)線程里去完成渲染工作嗎?比如使用 webworker?

          bac9181f3c2b2b457c9e6b5e47459005.webp

          但實(shí)際上這并不是 React 想要的, React 想要的是一種讓當(dāng)前的渲染工作變得更靈活的方案。

          f66bce00fe6ea218dd470b307d595674.webpReact Cong 2017

          我們有一些 IO 的工作,然后是一些 CPU 的工作,在理想狀況下,我們應(yīng)該能夠并行執(zhí)行其中一些工作了。這不是一個(gè)性能問(wèn)題,這基本上是一個(gè)調(diào)度問(wèn)題了 — React Cong 2017

          React 團(tuán)隊(duì)發(fā)現(xiàn),他們可以通過(guò)某種方式來(lái)優(yōu)化 React,以便可以區(qū)分低優(yōu)先級(jí)和高優(yōu)先級(jí)的工作。

          74cb26bb42d0fba660ce1bacb7a38ee3.webp

          例如,用戶輸入和動(dòng)畫(huà)渲染屬于高優(yōu)先級(jí)任務(wù),他們可以讓 React 擁有在這些任務(wù)之前互相切換的能力。

          理論上,通過(guò)這種方式,每個(gè) React 應(yīng)用的體驗(yàn)都可以得到提升,因?yàn)?React 總是最優(yōu)先考慮最重要的工作。

          這就是 React 團(tuán)隊(duì)這段時(shí)間做的事情,他們將其命名為 React Fiber。

          453b01a70e0259b3277a4b9e5c4ae3d9.webp

          Fiber 并沒(méi)有被作為一個(gè)新的框架,而是作為一個(gè)主要的 React 版本:React 16 推出來(lái)了。

          它讓 React 具有了異步可中斷的能力。

          異步渲染

          2017 年初,React 現(xiàn)在看起來(lái)更聰明一點(diǎn)了,它能夠優(yōu)先處理一些工作,并且能中斷當(dāng)前渲染。

          89b5528122628bbc8c04dc9550e3be0b.webp

          但是,這個(gè)能力只能說(shuō)是個(gè)半成品,另外還有一個(gè)非常困難的事情是找到一個(gè)公共 API,讓 React 開(kāi)發(fā)者以一種不會(huì)完全破壞當(dāng)前 React 生態(tài)的方式使用這些能力。

          解決這個(gè)問(wèn)題的第一部分,是擺脫掉可能會(huì)對(duì)新的異步可中斷渲染的能力起到副作用的部分。

          在新的架構(gòu)中,一個(gè)組件的渲染被分為兩個(gè)階段:第一個(gè)階段(也叫做 render 階段)是可以被 React 打斷的,一旦被打斷,這階段所做的所有事情都被廢棄,當(dāng) React 處理完緊急的事情回來(lái),依然會(huì)重新渲染這個(gè)組件,這時(shí)候第一階段的工作會(huì)重做一遍。兩個(gè)階段的分界點(diǎn),就是 render 函數(shù)。render 函數(shù)之前的所有生命周期函數(shù)(包括 render )都屬于第一階段。

          87e1e6910043cfa272cc8ce0f10b5eab.webpReact 16.3

          如果我們?cè)谶@些生命中期中引入了副作用,被重復(fù)執(zhí)行,就可能會(huì)給我們的程序帶來(lái)不可預(yù)知的問(wèn)題,所以到了 React v16.3,React 干脆引入了一個(gè)新的生命周期函數(shù) getDerivedStateFromProps,這個(gè)生命周期是一個(gè) 靜態(tài)方法,在里面根本不能通過(guò) this 訪問(wèn)到當(dāng)前組件,輸入只能通過(guò)參數(shù),對(duì)組件渲染的影響只能通過(guò)返回值。

          同時(shí),React 團(tuán)隊(duì)開(kāi)始將這種新的模式稱(chēng)為 — async rending。

          c42b19c18000c274dd929d9532ed222c.webpReact Conf 2018

          這里最大的問(wèn)題不是性能,而是調(diào)度,所以我們必須考慮調(diào)度,所以我們稱(chēng)這些新的能力為 async rending。我們的目標(biāo)是可以讓程序開(kāi)發(fā)者適應(yīng)設(shè)備和網(wǎng)速等用戶限制,讓交互體驗(yàn)變得更好。— React Conf 2018

          Hooks

          79af43ff564af23b5f7e0f6806dd7557.webp

          然而,一年后,dan 繼續(xù)表示:React 缺少了一些讓調(diào)度工作更簡(jiǎn)單的東西,這就是 Hooks

          8c8af0843e76f5e436b7956a83607390.webp

          Hooks2018 年十月在 React comp 中發(fā)布,它是 React 自發(fā)布以來(lái)最大的變化。

          01506f88185bf68f4488e0b569c058b0.webp

          Hooks 最初的重點(diǎn)在于它可以讓你用函數(shù)式寫(xiě)法替代類(lèi)來(lái)創(chuàng)建 React 組件。

          8b1f69f23d1fe2dbdd307c84947fe73a.webp

          但實(shí)際上它們帶來(lái)的收益要更多,你可以更好的進(jìn)行代碼復(fù)用、組合、設(shè)置默認(rèn)值,另外還有比較重要的一點(diǎn),Hooks 可以更自然的編寫(xiě)出和異步渲染更兼容的代碼。

          3c91cc73058d9d85a42bb9f313532bf4.webp

          concurrent React

          然后在這個(gè)階段我們還解鎖了一個(gè)新名字:concurrent React。

          744b9dc683640d31c6297a2e3fcf7f9a.webpReact Conf 2018

          async 是一個(gè)非常廣泛的術(shù)語(yǔ),它可以描述很多內(nèi)容,我們認(rèn)為 concurrent React 這個(gè)詞更恰當(dāng)一點(diǎn)。?concurrent React ?可以同時(shí)處理多個(gè)任務(wù),并且根據(jù)這些任務(wù)的優(yōu)先級(jí)在它們之間切換;它可以讓渲染樹(shù)進(jìn)行部分渲染,而不將最終結(jié)果提交給 DOM; 并且,最重要的, concurrent React 不會(huì)阻塞主線程。— React Conf 2018

          concurrent mode

          然而,這種說(shuō)法并沒(méi)有持續(xù)多久,很快它就會(huì) concurrent mode 替代了。

          事件來(lái)到了 2019 年,我們終于得到了一些可以拿出來(lái)用的東西,concurrent React 正式更名為 ?concurrent mode 。

          bf841600af03f2e6576eaf0e6acf4600.webpReact Conf 2019

          concurrent modeReact 應(yīng)用程序可以中斷較大的低優(yōu)先級(jí)任務(wù),以專(zhuān)注于更高優(yōu)先級(jí)的事情(例如響應(yīng)用戶輸入事件)?!?React Conf 2019

          4d3360a88f9c7bf8b28055bd904d355f.webp

          concurrent mode 現(xiàn)在已經(jīng)可以在實(shí)驗(yàn)?zāi)J较率褂昧??— React Conf 2019

          不容易,搞了三年了,用戶終于有一些可以使用的東西了。。。

          但是,它是最終版本的 API 嗎?不是!它已經(jīng)可以在生產(chǎn)環(huán)境使用了嗎?不能!

          2e8b3c0ebc34237f10a382997a108a64.webp

          但是,concurrent mode 讓我們終于可以在程序里面去體驗(yàn)一下了,我們可以在實(shí)驗(yàn)?zāi)J较麻_(kāi)啟,這樣我們就可以看到并發(fā)渲染的性能優(yōu)勢(shì)了。

          但是,實(shí)際上,想法很美好,我們?nèi)匀皇艿搅松?jí)策略的限制。

          升級(jí)策略

          React 在以前是不可以多版本共存的,這意味著我們只能在一些 DEMO 項(xiàng)目和新項(xiàng)目中看到這種提升,如果我們想在已經(jīng)存在的大型應(yīng)用程序里面去用,就需要一個(gè)更好的升級(jí)策略。

          640f4219b332f7c9ab4a8382919a8586.webp

          React 17 就是用來(lái)解決這個(gè)問(wèn)題的,它在一年后的 2020 年 8 月發(fā)布。

          beede586886547dc9a733d13161e291c.webp

          React 17 允許我們?cè)谕粋€(gè)應(yīng)用程序里允許多個(gè)版本的 React,這讓我們可以在大型項(xiàng)目里采用增量升級(jí)策略,你可以將程序的部分升級(jí)到 React 18。

          然而,它實(shí)際起到的作用也沒(méi)有那么好,因?yàn)闈u進(jìn)式的升級(jí)策略也無(wú)法做到更精細(xì)的控制。

          4392708f523451a0c1fbb320529baa03.webp

          React 團(tuán)隊(duì)還另外提供了一種稱(chēng)之為 blocking mode 的模式,是處于舊的模式和新的并發(fā)渲染模式之間的混合模式。

          怎么說(shuō)呢?也是個(gè)弱雞的策略,沒(méi)有達(dá)到預(yù)想的效果,React 團(tuán)隊(duì)在后續(xù)的一段時(shí)間收到了大量的用戶反饋。

          concurrent features

          01ac9999470b2483ceacf26cda821948.webp

          這時(shí),距離 React 宣布新的架構(gòu)開(kāi)始,已經(jīng)過(guò)去了 5 年的時(shí)間,在收到了大量的反饋后,React 團(tuán)隊(duì)又做出了改變,這次,似乎來(lái)到這最終的解決方案?

          3d19668b1d454790b772550ce8609815.webpReact Conf 2021

          在聆聽(tīng)了大量的用戶反饋后,我們很高興的分享 — concurrent modeReact 18 中消失掉了,它被逐步采用的漸進(jìn)式策略取代,你可以按照自己的節(jié)奏采用并發(fā)渲染。— React Conf 2021

          concurrent features — 這個(gè)名字很明顯,因?yàn)闊o(wú)法做到直接全面升級(jí)并發(fā)渲染,React 希望提供給我們一些特性讓我們?nèi)ミx擇性的啟用并發(fā)渲染。

          afafad1b6b9f8d63fcef9d96bae52f22.webp

          在這種模式下,你可以讓程序特定的部分啟用并發(fā)渲染。

          useDeferredValue

          0dbdb0d74da1fa8c36fdf8533f0e1a6c.webp

          我們需要通過(guò)一些 api,讓我們?cè)谡麄€(gè)渲染過(guò)程中確定工作的優(yōu)先級(jí),擁有可中斷的能力, 首先我們來(lái)看看 useDeferredValue ,它可以讓我們?nèi)?biāo)記某個(gè)具體狀態(tài)的優(yōu)先級(jí)。

          f44df9e543bc84332a4ade0eca451fc5.webp

          比如我們現(xiàn)在有這樣的場(chǎng)景,用戶輸入了一些搜索關(guān)鍵字后,我們需要將搜索到的數(shù)據(jù)渲染到下面的詳情里,如果這個(gè)處理比較耗時(shí),那么連續(xù)的用戶輸入會(huì)有卡頓的感覺(jué)。實(shí)際上,我們希望的是用戶的輸入能得到快速的響應(yīng),但是下面詳情的渲染多等待一會(huì)其實(shí)無(wú)所謂。

          79b0f8fd54097dbf14c98f16a7f09122.webp

          這時(shí),我們可以通過(guò) useDeferredValue 創(chuàng)建一個(gè) deferredText,真正的意思是 deferredText 的渲染被標(biāo)記為了低優(yōu)先級(jí),用戶輸入已經(jīng)不會(huì)有卡頓的感覺(jué)了。

          startTransition

          087b0268c8686c8cc7fe7106284b7806.webp

          useDeferredValue 是讓我們標(biāo)記哪些具體的狀態(tài)擁有更低的優(yōu)先級(jí),而 startTransition 可以明確的告訴 React 哪些更新具有更低的優(yōu)先級(jí)。

          0127d312c5a8dda1ab79a0f82fa85c5d.webp

          當(dāng)有一些更新被包裹在 startTransition 下時(shí),React 將已較低的優(yōu)先級(jí)去處理這些更新,從而優(yōu)先去處理像用戶輸入這樣更高優(yōu)先級(jí)的更新。

          Suspense

          0c362970941f6d1db61b9c901ce766a3.webp

          另外你可能還會(huì)經(jīng)常聽(tīng)到的一個(gè)詞是 Suspense,它的目標(biāo)是讓我們?cè)?React 組件中讀取遠(yuǎn)程數(shù)據(jù)像使用 propsstate 這樣簡(jiǎn)單。

          是一個(gè) React 組件,如果組件樹(shù)有一些位置還沒(méi)準(zhǔn)備好,它可以讓你以聲明的方式控制這部分渲染的 UI

          c9800cc447a8ba443170a30130a598b0.webp

          它可以讓我們將左側(cè)這樣代碼簡(jiǎn)化成右側(cè)這樣,讓你可以在 React 組件中以同步代碼的寫(xiě)法編寫(xiě)異步代碼。

          React 18 是最終版本嗎

          c145af36bbfc4e0cd7e354d91068e2e4.webp

          React 官方在官網(wǎng)中提到,大多數(shù)情況下我們都不會(huì)和這些并發(fā)渲染的 API 直接交互,這讓我們很難判斷 React 18 究竟是不是一個(gè)革命性的版本。

          b2da8677a1633df60eef54ba586d0c4c.webp

          不管怎么說(shuō),它是一個(gè)歷時(shí)兩千多天的、我們期待已久的巨大里程碑。

          你認(rèn)為它是 React 并發(fā)渲染的最終版本嗎?

          最后

          參考:

          • https://www.youtube.com/watch?v=NZoRlVi3MjQ
          • React 運(yùn)行時(shí)優(yōu)化方案的演進(jìn)

          如果你有任何想法,歡迎在留言區(qū)和我留言,如果這篇文章幫助到了你,歡迎點(diǎn)贊和關(guān)注。

          點(diǎn)贊在看是最大的支持??????

          瀏覽 87
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色视频网站在线观看免费 | 九九九九在线视频播放 | 免费看又色又爽又黄的成人用品 | 在线欧美日韩 | 成人视频免费 |