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
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:
- At the beginning, only two nodes, fiberRoot and rootFiber, were created
- Then create workInProgress Fiber according to jsx:
- Switch workInProgress Fiber to current Fiber
- At the beginning, only two nodes, fiberRoot and rootFiber, were created
update
- Create workInProgress Fiber based on current Fiber
- Switch workInProgress Fiber to current Fiber
- Create workInProgress Fiber based on 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.
- 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
- 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
- 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
3.react source code architecture
4. Source directory structure and debugging