preact icon indicating copy to clipboard operation
preact copied to clipboard

Asynchronous rendering pipeline based on microtask

Open yisar opened this issue 3 years ago • 0 comments

This is my new discovery, which can implement a diving model similar to React fiber in the logic of synchronous recursion.

According to my experience, I think except for time slicing, all other features are not unique to fiber.

Next, I introduce a technology that can simulate the execution stack similar to fiber, which is beneficial to the life cycles and suspense.

render(p, c){
  console.log('componentDidMount')
  c.resolve()
  if(c.children){
    for(let i =0; i< c.children.length; i++){
      p.childPromises.push(new Promise(r=>c.children[i].resolve= r))
      render(c, c.children[i], p)
    }
  }
  Promise.all(p.childPromises).then(res => {
    console.log('ParentComponentDidMount')
  })
}

Through the mechanism of passing promise, the parent component can know the behavior of the child component.

For Suspense

The core of Suspense is that when all subtrees are resolved, the Suspense component rerender. React using throw catch, child component throw and parent component catch.

For the two-phase rendering of React and the fallback of linked list, it is very easy. Fre only needs 10 lines of code to implement it:

https://github.com/yisar/fre/blob/master/src/reconciler.ts#L77

But for preact's single pass recursion, it costs more to implement the same API.

This is because it is difficult to control the behavior of the child component in a recursion. It will be possible to use new technology.

For Life Cycles

<A>
  <B>
    <C/>
  </B>
</A>

A - componentWillMount
B - componentWillMount
C - componentWillMount
C - componentDidMount
B - componentDidMount
A - componentDidMount

The reason why the life cycle is arranged in this way is that the traversal of the linked list has an upward backtracking feature.

while (fiber) {
    completeWork(fiber) // here
    if (fiber.sibling) return fiber.sibling
    fiber = fiber.parent
  }

Preact doesn't have a similar structure, so you often need additional data structures to achieve the same order.

Summary

Introducing an asynchronous rendering mechanism based on microtask can simulate the execution stack similar to React fiber, which is probably the most appropriate choice for preact. It is still synchronous, single pass and recursive.

Even it can reduce the size of the preact, making it possible to build a built-in Suspense.

yisar avatar Apr 23 '21 03:04 yisar