React Fiber 任務(wù)分片 & 時間分片

源碼基于react@16.13.1

Fiber 是一個工作單元唱歧,它的引入是react實現(xiàn)任務(wù)分片和時間分片的基礎(chǔ)。分片是為了在Reconciliation階段(純js計算粒竖,無DOM操作)一點一點地執(zhí)行任務(wù)颅崩,給瀏覽器喘息的機(jī)會,從而在體驗上給用戶更流暢的使用感受蕊苗。

任務(wù)分片

一個工作單元是什么沿后?可以從代碼中直觀地理解。

import React from 'react'
import ReactDOM from 'react-dom'

function App() {
    return (
        <div>
            <h1>Title</h1>
            <p>
                <a href='#'>link</a>
            </p>
        </div>
    )
}

ReactDOM.createRoot(document.getElementById('app')).render(<App />)

以上結(jié)構(gòu)朽砰,被react分解成了6個fiber尖滚,也就是6個工作單元,如下圖

react fiber

其中null對應(yīng)著fiber的根節(jié)點瞧柔,雖然在視覺上是什么都看不見的漆弄,但它的確在內(nèi)存里。剩下的fiber節(jié)點都比較好理解造锅。

每當(dāng)更新發(fā)生時撼唾,react會從fiber的根節(jié)點開始,一個一個地循環(huán)遍歷所有的fiber备绽。

react 通過循環(huán)券坞,一個一個地對fiber執(zhí)行performUnitOfWork操作,以此實現(xiàn)了任務(wù)分片肺素。

時間分片

時間分片的邏輯藏在循環(huán)里恨锚。

//react-reconciler -> ReactFiberWorkLoop.js
function workLoopConcurrent() {
  // Perform work until Scheduler asks us to yield
  while (workInProgress !== null && !shouldYield()) {
    workInProgress = performUnitOfWork(workInProgress);
  }
}

performUnitOfWork可能返回null或者下一個需要被執(zhí)行的fiber,返回結(jié)果存在workInProgress中倍靡。workInProgress在react-reconciler模塊中是全局變量猴伶。

當(dāng)shouldYield返回true的時候,循環(huán)語句中斷塌西,一個時間分片就結(jié)束了他挎,瀏覽器將重獲控制權(quán)。

以下任意條件成立時捡需,shouldYield會返回true

  • 時間片到期(默認(rèn)5ms)
  • 更緊急任務(wù)插隊

react 通過中斷任務(wù)循環(huán)办桨,實現(xiàn)了時間分片。

任務(wù)恢復(fù)

循環(huán)中斷時站辉,下一個未被完成的任務(wù)已經(jīng)被保存到react-reconciler模塊的全局變量workInProgress中呢撞。下一次循環(huán)開始時就從workInProgress開始。

跳出循環(huán)之后饰剥,react還做了一件事殊霞,通過MessageChannel發(fā)起了一個postMessage事件。

以上都發(fā)生在瀏覽器重獲控制權(quán)之前汰蓉。

而監(jiān)聽這個事件的绷蹲,正是循環(huán)的發(fā)起者performWorkUntilDeadline

// scheduler.development.js
const performWorkUntilDeadline = () => {
    if (scheduledHostCallback !== null) {
      const currentTime = getCurrentTime();
      deadline = currentTime + yieldInterval;
      const hasTimeRemaining = true;
      try {
        // 通過scheduledHostCallback發(fā)起workLoopConcurrent循環(huán)
        const hasMoreWork = scheduledHostCallback(
          hasTimeRemaining,
          currentTime,
        );
        if (!hasMoreWork) {
          isMessageLoopRunning = false;
          scheduledHostCallback = null;
        } else {
          port.postMessage(null); // 發(fā)起postMessage事件
        }
      } catch (error) {
        port.postMessage(null);
        throw error;
      }
    } else {
      isMessageLoopRunning = false;
    }
    needsPaint = false;
  };

  const channel = new MessageChannel();
  const port = channel.port2;
  channel.port1.onmessage = performWorkUntilDeadline;

循環(huán)中斷之后react執(zhí)行 port.postMessage 發(fā)起了一個message事件顾孽,并且通過事件監(jiān)聽又恢復(fù)了循環(huán)祝钢。在循環(huán)中斷到事件響應(yīng)的間隙,瀏覽器重獲了控制權(quán)若厚,執(zhí)行必要的渲染工作(如果有的話)太颤。

以上特性,目前只在開啟concurrent模式時有效盹沈。默認(rèn)模式下只有任務(wù)分片龄章,但是是同步執(zhí)行的,所以不存在時間分片乞封。


迅速搭建React源碼測試環(huán)境

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末做裙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肃晚,更是在濱河造成了極大的恐慌锚贱,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件关串,死亡現(xiàn)場離奇詭異拧廊,居然都是意外死亡监徘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門吧碾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凰盔,“玉大人,你說我怎么就攤上這事倦春』Ь矗” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵睁本,是天一觀的道長尿庐。 經(jīng)常有香客問我,道長呢堰,這世上最難降的妖魔是什么抄瑟? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮枉疼,結(jié)果婚禮上锐借,老公的妹妹穿的比我還像新娘。我一直安慰自己往衷,他們只是感情好钞翔,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著席舍,像睡著了一般布轿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上来颤,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天汰扭,我揣著相機(jī)與錄音,去河邊找鬼福铅。 笑死萝毛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滑黔。 我是一名探鬼主播笆包,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼略荡!你這毒婦竟也來了庵佣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤汛兜,失蹤者是張志新(化名)和其女友劉穎巴粪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡肛根,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年辫塌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片派哲。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡臼氨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出狮辽,到底是詐尸還是另有隱情,我是刑警寧澤巢寡,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布喉脖,位于F島的核電站,受9級特大地震影響抑月,放射性物質(zhì)發(fā)生泄漏树叽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望性锭。 院中可真熱鬧,春花似錦、人聲如沸瓮增。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吩谦。三九已至膝藕,卻和暖如春滑废,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豁延。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留苟鸯,地道東北人早处。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像么库,于是被迫代替她去往敵國和親亏掀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359