<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

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

    共 4488字,需瀏覽 9分鐘

     ·

    2022-05-12 03:10

    2161 天!

    86c002bff0f39d8ebc7cea909648dea1.webp

    這是 React 團隊從計劃為 React 增加 并發(fā)渲染 的能力,到 React 18 可用版本發(fā)布所花費的時間。

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

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

    瀏覽器的瓶頸

    早在 2016 年,React 就已經開始在前端屆爆火了。React 團隊始終有一個目標,就是給基于 React 而構建的上百萬個網站提供最好的性能體驗!

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

    54d58e00b8ee15357fe0bd6f7e7fe29c.webp

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

    通常情況下,它們互不打擾,相互運行的挺和諧的,但是如果一不小心,就有可能導致問題。

    65bfca302a78445ea1d72c55d71b262a.webpReact Conf 2018

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

    Fiber 誕生

    915d5cec313125e0ec6338c6cc2d8ed8.webp多線程渲染

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

    bac9181f3c2b2b457c9e6b5e47459005.webp

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

    f66bce00fe6ea218dd470b307d595674.webpReact Cong 2017

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

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

    74cb26bb42d0fba660ce1bacb7a38ee3.webp

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

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

    這就是 React 團隊這段時間做的事情,他們將其命名為 React Fiber。

    453b01a70e0259b3277a4b9e5c4ae3d9.webp

    Fiber 并沒有被作為一個新的框架,而是作為一個主要的 React 版本:React 16 推出來了。

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

    異步渲染

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

    89b5528122628bbc8c04dc9550e3be0b.webp

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

    解決這個問題的第一部分,是擺脫掉可能會對新的異步可中斷渲染的能力起到副作用的部分。

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

    87e1e6910043cfa272cc8ce0f10b5eab.webpReact 16.3

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

    同時,React 團隊開始將這種新的模式稱為 — async rending

    c42b19c18000c274dd929d9532ed222c.webpReact Conf 2018

    這里最大的問題不是性能,而是調度,所以我們必須考慮調度,所以我們稱這些新的能力為 async rending。我們的目標是可以讓程序開發(fā)者適應設備和網速等用戶限制,讓交互體驗變得更好?!?React Conf 2018

    Hooks

    79af43ff564af23b5f7e0f6806dd7557.webp

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

    8c8af0843e76f5e436b7956a83607390.webp

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

    01506f88185bf68f4488e0b569c058b0.webp

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

    8b1f69f23d1fe2dbdd307c84947fe73a.webp

    但實際上它們帶來的收益要更多,你可以更好的進行代碼復用、組合、設置默認值,另外還有比較重要的一點,Hooks 可以更自然的編寫出和異步渲染更兼容的代碼。

    3c91cc73058d9d85a42bb9f313532bf4.webp

    concurrent React

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

    744b9dc683640d31c6297a2e3fcf7f9a.webpReact Conf 2018

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

    concurrent mode

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

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

    bf841600af03f2e6576eaf0e6acf4600.webpReact Conf 2019

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

    4d3360a88f9c7bf8b28055bd904d355f.webp

    concurrent mode 現(xiàn)在已經可以在實驗模式下使用了 ?— React Conf 2019

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

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

    2e8b3c0ebc34237f10a382997a108a64.webp

    但是,concurrent mode 讓我們終于可以在程序里面去體驗一下了,我們可以在實驗模式下開啟,這樣我們就可以看到并發(fā)渲染的性能優(yōu)勢了。

    但是,實際上,想法很美好,我們仍然受到了升級策略的限制。

    升級策略

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

    640f4219b332f7c9ab4a8382919a8586.webp

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

    beede586886547dc9a733d13161e291c.webp

    React 17 允許我們在同一個應用程序里允許多個版本的 React,這讓我們可以在大型項目里采用增量升級策略,你可以將程序的部分升級到 React 18

    然而,它實際起到的作用也沒有那么好,因為漸進式的升級策略也無法做到更精細的控制。

    4392708f523451a0c1fbb320529baa03.webp

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

    怎么說呢?也是個弱雞的策略,沒有達到預想的效果,React 團隊在后續(xù)的一段時間收到了大量的用戶反饋。

    concurrent features

    01ac9999470b2483ceacf26cda821948.webp

    這時,距離 React 宣布新的架構開始,已經過去了 5 年的時間,在收到了大量的反饋后,React 團隊又做出了改變,這次,似乎來到這最終的解決方案?

    3d19668b1d454790b772550ce8609815.webpReact Conf 2021

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

    concurrent features — 這個名字很明顯,因為無法做到直接全面升級并發(fā)渲染,React 希望提供給我們一些特性讓我們去選擇性的啟用并發(fā)渲染。

    afafad1b6b9f8d63fcef9d96bae52f22.webp

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

    useDeferredValue

    0dbdb0d74da1fa8c36fdf8533f0e1a6c.webp

    我們需要通過一些 api,讓我們在整個渲染過程中確定工作的優(yōu)先級,擁有可中斷的能力, 首先我們來看看 useDeferredValue ,它可以讓我們去標記某個具體狀態(tài)的優(yōu)先級。

    f44df9e543bc84332a4ade0eca451fc5.webp

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

    79b0f8fd54097dbf14c98f16a7f09122.webp

    這時,我們可以通過 useDeferredValue 創(chuàng)建一個 deferredText,真正的意思是 deferredText 的渲染被標記為了低優(yōu)先級,用戶輸入已經不會有卡頓的感覺了。

    startTransition

    087b0268c8686c8cc7fe7106284b7806.webp

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

    0127d312c5a8dda1ab79a0f82fa85c5d.webp

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

    Suspense

    0c362970941f6d1db61b9c901ce766a3.webp

    另外你可能還會經常聽到的一個詞是 Suspense,它的目標是讓我們在 React 組件中讀取遠程數(shù)據像使用 propsstate 這樣簡單。

    是一個 React 組件,如果組件樹有一些位置還沒準備好,它可以讓你以聲明的方式控制這部分渲染的 UI

    c9800cc447a8ba443170a30130a598b0.webp

    它可以讓我們將左側這樣代碼簡化成右側這樣,讓你可以在 React 組件中以同步代碼的寫法編寫異步代碼。

    React 18 是最終版本嗎

    c145af36bbfc4e0cd7e354d91068e2e4.webp

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

    b2da8677a1633df60eef54ba586d0c4c.webp

    不管怎么說,它是一個歷時兩千多天的、我們期待已久的巨大里程碑。

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

    最后

    參考:

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

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

    點贊在看是最大的支持??????

    瀏覽 87
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    免费无码一区二区三区 | 毛A黄片一级 | www.91av视频在线 | 抽插 久久 | 操逼免费在线观看 |