Advanced

Kyle Mo

 

Become a better React Developer

React Concepts - (1)

為什麼要了解底層實作?

  • 成為專家 (你會去跟不懂車的銷售買車嗎?)
  • 有機會成為技術的生產者(ex: React Core Team, npm packages)
  • 對面試有幫助
  • 很多 Aha Moment (你會知道為什麼程式是這樣執行)

面試官:用 React 開發聽說效能比較好,為什麼?

(Breakout Rooms 5 Mins)

1. 第一個印出 false,第二個印出 true
2. 第一個印出 true,第二個印出 false
3. 兩個都印出 false
4. 兩個都印出 true

 

const [isLoading, setIsLoading] = useState(false);

const handleClick = () => {
    console.log('isLoading: ',isLoading)
    setIsLoading(true)
    console.log('isLoading: ',isLoading)
}

兩次印出的 count 分別為多少?count state 的值實際上是多少?

const [count, setCount] = useState(0);

const handleClick = () => {
    console.log('count: ',count)
    setCount(count + 10)
    setCount(count + 10)
    setCount(count + 10)
    console.log('count: ',count)
}

A: 0, 0, 10

const [count, setCount] = useState(0);

const handleClick = () => {
    console.log('count: ',count)
    setCount(prev => prev + 10)
    setCount(prev => prev + 10)
    setCount(prev => prev + 10)
    console.log('count: ',count)
}

兩次印出的 count 分別為多少?count state 的值實際上是多少?

A: 0, 0, 30

Why ?

  • 為什麼可以做到 Concurrent Rendering ?
  • 為什麼可以做到 Suspense ?
  • 為什麼可以做到 Streaming SSR ?
  • 為什麼可以做到 Selective Hydration ?

React Basic

Virtual DOM -> Diff Algo -> DOM Operation

What is DOM ?

文件物件模型(Document Object Model, DOM)是 HTML、XML 和 SVG 文件的程式介面。它提供了一個文件(樹)的結構化表示法,並定義讓程式可以存取並改變文件架構、風格和內容的方法。(From MDN)

  1. 渲染時,React 會先複製一份 DOM 的物件(即為Virtual DOM)
  2. 當 React component 的 states or props 改變時,會比對先前的 Virtual DOM 和新的 Virtual DOM 差異,這個流程稱之為 diffing
  3. Virtual DOM 先用自己的演算法 (diff) 算出實際需要更新的部分,比對兩者差異之後,再去更動真實的 DOM,有效減少渲染的次數 ,提高效能(批次更新)

 

Virtual DOM 流程

Q:為什麼更新 Virtual DOM 比更新真實 DOM 快?

A:因為 Virtual DOM 其實只是一個 JS Object

這個架構還是遇到一些瓶頸...

React Fiber Architecture

Outline

What is React Fiber ?

React Reconciler

Overview of fiber reconciler algorithm

What Fiber brings for the future ?

Why Fiber use linked list to walk component tree?

What is React Fiber ?

  • 發佈於 React 16,是 React 對內部資料結構的一個 refactor
  • 是 React 未來許多特性與功能實踐的基礎 (ex. Concurrent Mode, Suspense Data Fetching)
{
    stateNode: new ClickCounter,
    type: ClickCounter,
    alternate: null,
    key: null,
    updateQueue: null,
    memoizedState: {count: 0},
    pendingProps: {},
    memoizedProps: {},
    tag: 1,
    effectTag: 0,
    nextEffect: null
}
  • Fiber 也代表 an unit of work for React to process

Animation

Responsiveness

  • 將任務切分成 Chunks
  • 將任務 Prioritize 分優先級
  • 任務可以暫停,之後再繼續
  • 可以重複使用之前的 work,也可以將不需要的 work 丟棄掉

&

What can it do ?

CPU / IO

JSX -> React Element -> Fiber Node

What we know about fiber for now ?

There is tree of connected fibers

They represent react element and other things as well

Fibers are processed in two phase 

Fiber = unit of work

- Render Phase 

- Commit Phase 

Synchronous

Asynchronous

 React Reconciliation

 為什麼原來的 Diffing 要 O(n³) ?

具體來說,想像我們有兩棵樹:舊樹和新樹。我們要遍歷舊樹中的每個節點,並與新樹中的每個節點進行比較。這本身就是 O(n²)。但是,當我們考慮到可能的子節點和子樹的變化時,我們必須再次進行類似的遍歷,導致 O(n³) 的算法複雜度。

A
├── B
│   ├── D
│   └── E
└── C


A
├── B
│   ├── D
│   └── F
└── C

Before Fiber

After Fiber

Reconciler

Renderer

Scheduler

Reconciler

Renderer

- Reconciliation 是實作在 React Core 裡,不同 renderer 共用 Diff 演算法

- Renderer 代表 ReactDOM, React Native,各自負責渲染元件到畫面上

Old Reconciler - Stack (< React 16)

- Work synchronous

- Work recursively, like call stack

- Had to work until the stack is empty

Fiber

Reconciler

New Reconciler -

Fiber Tree

Virtual DOM  ->

Why Fiber use linked list to walk component tree?

node1

node2

node3

What does browser do in 1 frame ?

Render Phase

Commit Phase 

  • retrieves the children from the component
  • updates state and props
  • calls lifecycle hooks
  • compares them to the previous children and figures out the DOM updates that need to be performed

React walk the fiber tree and....

What is the problem ?

React is going to walk the entire tree of components synchronously and perform work for each component

It may run over 16 ms

Will cause frames to drop causing stuttering visual effects.

rIC, rAF To The Rescue

requestIdleCallback((deadline) => {
    //while we have time, perform work for a part of the components tree
    while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && nextComponent) {
        nextComponent = performWork(nextComponent);
    }
});

rAF: high priority task (animation)

rIC: low priority task (network request)

Well...we have big trouble....the work can not broke into smaller chunks

React just keeps iterating until it processed all components and the stack is empty.

synchronous

walk(a1);

function walk(instance) {
    doWork(instance);
    const children = instance.render();
    children.forEach(walk);
}

function doWork(o) {
    console.log(o.name);
}

Stack -> Linked List

Uses a linked list tree traversal algorithm. It makes it possible to pause the traversal and stop the stack from growing!

Fiber Linked List traversal

- one child

- one sibling

- one return

How React Process A Fiber Tree ?

A

B-1

B-1

B-2

B-3

C-1

D-1

D-2

= begin

= complete

1. DFS

2. child -> 自身 -> sibling

Stack doesn’t grow as we walk down the tree

Overview of fiber reconciler algorithm

Render Phase 

Commit Phase 

Pre-Required Knowledges

- Current & Work In Progress Tree

alternate

Side Effects

- mutating the DOM

- calling lifecycle methods

Render

Commit

Each fiber node can have effects associated with it. They are encoded in the effectTag field.

So effects in Fiber basically define the work that needs to be done for instances after updates have been processed.

Synchronous

Effects List

Run Through The Process

1. JSX -> React Elements (tree)-> Fiber Nodes (tree)

2. state change , re-render : JSX -> React Elements (tree)-> Fiber Nodes marked with side effect (WorkInProgress tree)

Asynchronous Render Phase

Some lifecycle methods run in render phase, can't operate DOM

3. Turn WorkInProgress tree to current

Render Phase ->    Tree of fibers + List of effects

How effects applied ?

- commit phase, React go through the effect list and applied them to component instance

- synchronously, user can see these changes

Some lifecycle methods run in commit phase

 What Fiber Brings For The Future ?

Concurrent Mode || Concurrent Features

Suspense

Use web worker to parallelize works

Use WebAssembly

 Recap

- React use fiber architecture to refactor since v16

- Fiber represent 'unit of work' 

- Not all for performance, it makes React smarter

- Two phase of Fiber Reconciler: render (async) -> commit (sync)

- From stack to linked list

- Is the base of many React's future features

面試官:

  1. 用 React 開發聽說效能比較好,為什麼?

  2. 為什麼新版 React 可以做到 Concurrent Rendering ?

 

Retro Time

課後閱讀

作業

  • 會後必讀
  • Issue 心得(分享 + 會後必讀)
  • Before 第二次分享(我會催繳喔!)
  • 歡迎跟我預約 Peer Sharing !

Kahoot!

Made with Slides.com