阅读 322

fre 的异步渲染(concurrent mode)

halo,大家好,我是 132 真的好久不见呢……

这次给大家带来的是 fre v1.7 的异步渲染

异步渲染是一个非常厉害的东西,也是 react16 搞了三年,至今还没正式确定的

在这三年间,不断改名,fiber增量渲染,async mode,时间切片,concurrent mode

反正最终都是没有被确定就是了

其实我最开始写 fre 的时候,也是为了搞清楚这玩意才写的,虽然一直到 v1.7 才搞定

废话不多说,直接上 demo~

codesandbox.io/s/suspiciou…

这个是 fre 的 rasmus 叔叔写的用例,里面有 react 和 preact 的依赖,可以通过取消注释来切换

大家可以看到,使用 fre 进行异步渲染丝毫顺滑,但是切换到 preact 等同步渲染的框架,就会明显卡顿

这是三十个组件,可以手动调整到一百个,二百个,一千个………………

真的会卡到怀疑人生,哈哈

当然,目前除了 fre 和 react,其他所有框架都是同步渲染,都会这么卡

什么是异步渲染

其实了解 react 的应该都知道,异步渲染是一个优先级任务调度,高优先级任务会优先执行,低优先级任务会被打算,并可以继续和回退

这块有很多文章介绍,就不用我多说啦

react 的异步渲染

react 的异步渲染,在之前是使用 requestAnimationFrame 实现的

requestAnimation 在重绘之前执行,然后,他会把更新遍历的工作先放到 message channel(宏任务队列)中,然后利用 rAF 和 MC 之间的阈值,来实现优先级调度

期间它需要根据时间进行帧率的动态计算,所以每次其实帧率都是不准确的,但都所差无几,达到一个平衡状态

我认为这是一个不那么好的实现,因为它需要计算帧和帧率,万一碰上坑的电脑,卡那么一下,就死定了

react v16.10 更新了这个算法,又更新了 API,将 concurrentMode 移除,现在改名叫 createRoot

import { unstable_createRoot } from "react-dom"

const root = unstable_createRoot(document.getElementById('root'))
root.render(<App />)
复制代码

vue3 的时间切片

vue3 最近公开源码,我也去看了下,其实时间切片是我最感兴趣的部分

vue3 的实现原理是利用 promise 来做,它利用 promise 的等待行为来模拟低优先级任务被打断

当然 vue3 的实现其实还是不够的(只是组件级别),它天生没有一个好的数据结构(链表),导致这种事情实现起来,不那么优雅

fre 的异步渲染

以上,react 和 vue 两种实现都不那么靠谱的情况下

fre 使用了新的思路,不使用 requestAnimationFrame 也不是 promise,它使用了 message channel,来尽可能多执行低优先级任务

这个思路又完美,代码量又小,又容易理解

fre 默认开启了异步渲染,不需要额外的 API

总结

综上所述,不同框架给出了不同的实现思路

但用例都是一样的,除了 vue3 的不完全实现最终没有出现在 master 分支

fre 和 react 都可以用来应对大量数据的渲染

异步渲染对于框架而言,是非常重要的一环,虽然现在真正意义上支持异步渲染的框架只有 fre 和 react,但异步渲染是将传统的 diff 算法性能对比的层面彻底垄断了

毕竟以前 diff 的时候,无论你算法多么好,总有大量数据的情况是搞不定的

现在小数量的数据,diff 算法不用写的太厉害,也不会很卡,而大量数据有异步渲染,更是丝毫顺滑

最终,fre v1.7 以后,两个核心算法都稳定了,测试覆盖率也达到了 80%(WIP)

现在 fre 的主要开发人员是两人,rasmus 叔叔最近在做测试工作

欢迎试用与 star: github.com/132yse/fre

也欢迎加入我们,一起研究哈!

关注下面的标签,发现更多相似文章
评论