Interviewer: how do you understand Fiber

Interviewer: how do you understand Fiber

hello, this is Xiaochen. Let's talk about Fiber today. I don't know if you have encountered any questions related to react Fiber during the interview. This kind of question is relatively open, but it is also a question to investigate the depth of understanding of react source code. If you interview the senior front-end post, it happens that you usually use react, then this interview question is one you must know.

Why are large applications slow

Why were the previous applications slow? When building complex large-scale applications for traditional front-end applications, such as js native or jquery applications, the mutual operation and update of various pages are likely to cause page redrawing or rearrangement, and frequent operation of these DOMS is actually very performance consuming

Looking at the following figure, this is an attribute on a node. You can see that there are many attributes on a node. In complex applications, operating these attributes may cause a large number of node updates accidentally. How to improve the performance of the application?

const div = document.createElement('div');
let str = ''
for(let k in div){
  str+=','+k
}
console.log(str)

Why does Fiber appear

From version 15 to 17 and 18, react has undergone great changes internally. All this is centered on a goal, which is asynchronous and interruptible update, and the final result of this goal is to build fast response applications.

Complex applications may update a large number of DOMS when updating, so react adds a layer of Fiber between the application layer and dom layer, and Fiber works in memory. Therefore, when updating, it only needs to compare dom updates in memory, and finally apply it to the real nodes that need to be updated

This leads to a process of comparing new and old nodes, and the calculation of comparing two trees is actually very performance consuming. react proposes a diff algorithm to reduce the complexity of comparison. For the specific diff process, please refer to previous articles diff algorithm

However, in the face of more and more complex applications, diff algorithm still consumes a long time slice. Without optimization, react is still unable to compare fibers and update the state on nodes,

  • Before react15, the comparison process was called stack reconcile. Its comparison method is "one way to black", that is, the comparison process can not be interrupted. What happens? For example, when a page rendering operation consumes performance, if the user performs some operations at this time, it will get stuck, The application will not appear smooth.
  • After react16, the scheduler and the Lane model of react17 appear. They can work together, divide the time-consuming tasks into work units according to the Fiber node, and traverse the Fiber tree to calculate or update the status on the node. They can be interrupted, continued, and interrupted by high priority tasks. For example, the update triggered by the user is a high priority task, High priority tasks is too laggy to use.

What is Fiber

This is what react needs to do. React innovatively proposes jsx, which declaratively describes the effect of page rendering. jsx will be parsed into react by babel through ast CreateElement, and react After the createElement function is executed, it is a jsx object or virtual dom

  • During mount, that is, during the first rendering, the render stage will generate new Fiber nodes according to the jsx object, and then these Fiber nodes will be marked with the side effect of 'Placement', indicating that they are new nodes and need to be inserted into the real nodes. In the commit stage, the real nodes will be operated and inserted into the dom tree.
  • During update, that is, when the application triggers the update, the render stage will compare the latest jsx with the old Fiber to generate new fibers. These fibers will have various side effects, such as' Deletion ',' Update ',' Placement ', etc. this comparison process is diff algorithm , in the commit phase, the real node will be operated and the corresponding side effects will be executed.

If you don't know about the render phase and the commit phase, you can view previous articles

8.render stage

10.commit phase

Fiber has many meanings, which can be understood from the following perspectives:

  • Work unit task decomposition: Fiber's most important function is to save the corresponding information (including priority) of native nodes or component nodes as work units. These nodes form a Fiber tree through the shape of pointers
  • Incremental rendering: through the comparison between jsx object and current Fiber, the minimum difference patch is generated and applied to real nodes
  • Pause, resume, and arrange priorities according to priority: the Fiber node saves priorities, which enables tasks to pause, resume, and arrange priorities by comparing the priorities of different nodes. It also provides a basis for the upper layer to realize batch update and suspend
  • Save state: because Fiber can save state and updated information, it can update the state of function components, that is, hooks

Data structure of Fiber

The built-in properties of Fiber are as follows:

//ReactFiber.old.js
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  //Save node information as a static data structure 
  this.tag = tag;//Type of corresponding component
  this.key = key;//key attribute
  this.elementType = null;//Element type
  this.type = null;//func or class
  this.stateNode = null;//Real dom node

  //As the number of fibers, the architecture is connected into a fiber tree
  this.return = null;//Point to parent node
  this.child = null;//Point to child
  this.sibling = null;//Point to sibling node
  this.index = 0;

  this.ref = null;

  //Use as a unit of work to calculate state
  this.pendingProps = pendingProps;
  this.memoizedProps = null;
  this.updateQueue = null;
  this.memoizedState = null;
  this.dependencies = null;

  this.mode = mode;
    
    //effect related
  this.effectTag = NoEffect;
  this.nextEffect = null;
  this.firstEffect = null;
  this.lastEffect = null;

  //Priority related attributes
  this.lanes = NoLanes;
  this.childLanes = NoLanes;

  //Pointers to current and workInProgress
  this.alternate = null;
}

How does Fiber work

Now we know that Fiber can save the real dom, and the Fiber node corresponding to the real dom in memory will form a Fiber tree. This Fiber tree is called current Fiber in react, that is, the Fiber tree corresponding to the current dom tree, and the Fiber tree under construction is called workInProgress Fiber. The nodes of the two trees are connected through alternate

function App() {
  return (
        <>
      <h1>
        <p>count</p> xiaochen
      </h1>
    </>
  )
}

ReactDOM.render(<App />, document.getElementById("root"));

Building workInProgress Fiber occurs in createWorkInProgress, which can create or take Fiber

//ReactFiber.old.js
export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
  let workInProgress = current.alternate;
  if (workInProgress === null) {//Distinguish between mount and update
    workInProgress = createFiber(
      current.tag,
      pendingProps,
      current.key,
      current.mode,
    );
    workInProgress.elementType = current.elementType;
    workInProgress.type = current.type;
    workInProgress.stateNode = current.stateNode;
   
    workInProgress.alternate = current;
    current.alternate = workInProgress;
  } else {
    workInProgress.pendingProps = pendingProps;//Reuse attribute
    workInProgress.type = current.type;
    workInProgress.flags = NoFlags;

    workInProgress.nextEffect = null;
    workInProgress.firstEffect = null;
    workInProgress.lastEffect = null;
    
    //...
  }

  workInProgress.childLanes = current.childLanes;//Reuse attribute
  workInProgress.lanes = current.lanes;

  workInProgress.child = current.child;
  workInProgress.memoizedProps = current.memoizedProps;
  workInProgress.memoizedState = current.memoizedState;
  workInProgress.updateQueue = current.updateQueue;

  const currentDependencies = current.dependencies;
  workInProgress.dependencies =
    currentDependencies === null
      ? null
      : {
          lanes: currentDependencies.lanes,
          firstContext: currentDependencies.firstContext,
        };

  workInProgress.sibling = current.sibling;
  workInProgress.index = current.index;
  workInProgress.ref = current.ref;


  return workInProgress;
}
  • During mount: fiberRoot and rootFiber will be created, and then Fiber nodes will be created according to jsx objects, and the nodes will be connected into a current Fiber tree.
  • During update: jsx (render of ClassComponent or return value of FuncComponent) and current Fiber will be formed into a Fiber tree called workInProgress according to the new state (diff algorithm), and then the current of fiberRoot will point to the workInProgress tree. At this time, workInProgress will become current Fiber. fiberRoot: refers to the root node of the entire application. There is only one

    fiberRoot: refers to the root node of the entire application. There is only one

    rootFiber: ReactDOM.render or reactdom unstable_ There can be multiple application nodes created by createroot.

    We now know that there are two fiber trees, current Fiber and workInProgress Fiber. Fiber dual cache means that a new workInProgress Fiber is formed after reconciling (diff), and then the workInProgress Fiber is switched to current Fiber and applied to the real dom. The advantage of dual fiber is that the description of the view is formed in memory and finally applied to the dom, Reduced DOM operations.

Now let's take a look at the process diagram of Fiber dual cache creation:

  • When mount:

    1. At the beginning, only two nodes, fiberRoot and rootFiber, were created
    2. Then create workInProgress Fiber according to jsx:
    3. Switch workInProgress Fiber to current Fiber
  • update

    1. Create workInProgress Fiber based on current Fiber
    2. Switch workInProgress Fiber to current Fiber

Why can Fiber improve efficiency

Fiber is a js object that can carry node information, priority and updateQueue. At the same time, it is also a unit of work.

  1. Fiber dual cache can be switched to current Fiber after the wip Fiber tree is built. It can be switched directly in memory at one time to improve the performance
  2. The existence of Fiber makes it possible to update asynchronously and interruptably. As a work unit, you can execute work in the time slice. When there is no time, return the execution right to the browser. The Fiber returned after pausing before the next time slice continues to execute
  3. Fiber can perform the corresponding diff update during reconcile, so that the final update can be applied to the real node

Video Explanation (efficient learning): Click to learn

Previous react source code analysis articles:

1. Introduction and interview questions

2. Design concept of react

3.react source code architecture

4. Source directory structure and debugging

5. JSX & Core api

6.legacy and concurrent mode entry functions

7.Fiber architecture

8.render stage

9.diff algorithm

10.commit phase

11. Life cycle

12. Status update process

13.hooks source code

14. Handwritten hooks

15.scheduler&Lane

16.concurrent mode

17.context

18 event system

19. Handwritten Mini react

20. Summary & answers to interview questions in Chapter 1

Keywords: React

Added by czs on Fri, 10 Dec 2021 03:48:49 +0200