Yingchen Xue monkingxue @Tencent Shanghai FrontEnd Engineer

startedWebAssembly/WASI

started time in 13 days

startedCraneStation/wasmtime

started time in 16 days

startedMicrosoft/frontend-bootcamp

started time in 16 days

startedMicrosoft/pyright

started time in 16 days

startedtobie/specref

started time in a month

startedjozefg/learn-tt

started time in a month

issue comment132yse/fre

思考 fre 重构

  1. vue-hooks 的实现是错误的,它起不到 hooks 的作用

1.你所谓的 hooks 的作用是什么呢?

2.光 ric 为什么可以处理大量数据计算呢?一个计算任务需要10s,那么不论放在哪里执行,都会影响页面响应。应该做的是把任务拆分成 100 个,一个 0.1s,然后挨个执行,在执行之中如果需要响应交互,可以方便地暂停计算任务,转而响应交互。

3.我不认为 vue 的 hooks 「实现」是错误的。因为 hooks 的本质是语义正确而不是实现正确,为什么会有 「实现错误」这种说法呢?

132yse

comment created time in a month

issue comment132yse/fre

思考 fre 重构

但是如果是大量数据提高响应能力,那也不需要 fiber ,直接 requestIdleCallback 就可以,不用弄一个链表的遍历

我觉得你可能需要去了解一下 fiber 的来源和目的。如果只是为了拓展控制流(你说的 suspense等),那用 异常控制流可以实现(当然 return value 需要全局设置一下)。一个很直接的例子就是 vue 没有 fiber,但是不妨碍他实现 hooks,hooks 是 algebraic effects 上的抽象,fiber 就是 algebraic effects 的在 react 中的体现。

但是在大量数据下的交互相应,就必须要能够精准地往返于 work 之间,而 requestIdleCallback 只是延迟运算,不是拆分运算,只要运算很密集,那响应就不会那么及时。所以问题的关键除了需要利用 idle 片段,还必须合理拆分计算。react 的 fiber 是以 vnode 为单位做拆分的,这种拆分最终也很好地降低了单次运算时间,将运算开销分摊开。

还有个佐证就是 Dan 的 这个对比视频

当然,我们也不能否认 fiber 对于控制流的拓展性带来的抽象提升,但是何为主何为次我保留态度了。

132yse

comment created time in a month

issue comment132yse/fre

思考 fre 重构

fiber 本就无法提高性能,它的核心场景也不是大量数据渲染,任何时候,一股脑渲染大量数据都是不可取的

fiber 确实无法提高性能,但是大量数据渲染确实是有很多 case 的,比如说可视化。fiber 的场景应该是为复杂数据挑战下的高响应性提供支持,而「可重入性」是 fiber 这种结构的一个特点罢了。

难道没有 fiber 就无法实现 susponse?很明显不,利用异常控制流也很容易实现,fiber 的「可重入性」在异步上的作用可能并没有分段 reconcile 重要,很直接的就是,一个只是开发习惯上的改变,而另一个则是实打实的富交互性能体验上的提升。

132yse

comment created time in a month

issue comment132yse/fre

思考 fre 重构

react like vdom 下场景的性能瓶颈主要来源于 reconcile 和 patch(commit) 这两个过程,fiber 的 commit 也是不能打断的,所以性能无法更好优化。

而 didact 的 vdom diff 算法很有问题,比如说在做 sibling diff 的时候不会中断,会一直运行,这种 diff 算法在长列表场景极其吃亏,而有意思的是这种复杂场景按理来说应该是 fiber 的重要场景。

132yse

comment created time in a month

issue comment132yse/fre

跟你

递归是同层的遍历...

为什么递归是同层的遍历?同层使用普通的迭代就可以 diff,而不同层的遍历才应该是递归(比如说递归的 DFS 实现)。 而且原先的 stack reconciler 也是不存在所谓「孙子节点」,因为只会保存 children 的信息,而你说带 key 的 children 的 children 改变了,那会复用上层的 dom,只修改最底层的 dom

william-xue

comment created time in a month

issue comment132yse/fre

跟你

整体架构和 didact 几乎一致,fiber 核心代码……

目前 fre 的 fiber 实现是不正确的 重点不是 diff 没有 keyed 目前 fre 的致命错误在于,没有高低优先级的调度 didiact 也是如此,fre 目前通过宏任务强制每次更新都会高优先级的开启一次遍历……而整个遍历、渲染都是低优先级……这是错误的 至于 diff,我个人认为,由于没有了递归,我觉得 keyed 的重复利用率不会太高 但是确实也是一个缺陷

综上,我大概放假搞下一个版本:

  1. 重构 fiber,写死优先级
  2. 重构 diff,加 keyed
  3. 重构更新策略,争取低优先级任务全为微任务

key 和递归没什么关系,因为 key 解决的 list 比较的问题,而在比较 list 的时候是不用递归的(循环算 mini patches)就好。目前的问题是连续数组和链表在算最小变动的时候难度不一样,所以 react 的 fiber 专门加了 index prop 来支持对链表的类数组访问

william-xue

comment created time in a month

issue comment132yse/fre

跟你

整体架构和 didact 几乎一致,fiber 核心代码几乎一点没变,最好还是写个 ref or thx 吧。

另外 didact 本身的 diff 过于简单,实用性不高,比如说连 key 都不支持,如果要增强实用性这块需要大改。

william-xue

comment created time in a month

startedWICG/import-maps

started time in 2 months

starteddenolib/high-res-deno-logo

started time in 2 months

startedhmemcpy/milewski-ctfp-pdf

started time in 3 months

more