fre 更新了,框架设计重思考……

4,603 阅读4分钟

halo 大家好,好久不贱呢~

好久没出来浪了::>_<::,主要是之前在重构 c站,现在重构完了

是时候重构一下俺的轮子了……

所以,如你所见,smox、fre、eplayer 都更新了

这篇文章,主要来说说,fre 框架的设计

Use

import { h, render, useState } from 'fre'

function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

render(<Counter />, document.getElementById('root'))

这段代码大家应该很熟悉啦,react hooks API 就是个奇迹

而我,看到这种正常思维根本想不出怎样实现的 API 天生有种痴迷

本质

react hooks API 为什么难以实现,其实本质是 this 的缺失

如果这是 vue,我们可以通过依赖收集的时候,知道是哪个组件,然而 react 并没有

事实上,react 的 hooks 是存在于 fiber 的

原理

唉,一不小心又说到 fiber 了,好尴尬

fiber 网上的文章蛮多的,大多写的都云里雾里,对于 hooks 而言,其实关键在于 链表的遍历

连表的遍历和递归遍历不一样的是,链表能够一条链走完所有的节点

而递归的兄弟节点是断连的

什么意思,就是说,fiber 能够使得我们走一遍,能够顺序的拿到所有的 function 节点,然后,有个全局变量在更替,这个就是我们要的 this 了

设计哲学

唔,上面说了一点点 hooks 内容,好像跑题了……

重点还是框架设计哈!其实框架,是个人喜好的不同搭配,仅此而已

尺寸 组件化 状态更新
fre 1kb hooks Fiber
preact 3kb class diff
vue 10kb SFC Proxy + diff
react 33kb class + hooks Fiber

以上,先看个表格,我马上,要开始编作文了

组件化

对于一个框架来说,组件化是很重要的,比如 react 主要是 class 的方案,vue 是模板引擎和单文件,fre 是 function ……

首先,我是很不喜欢 vue 的 模板引擎的,这是真的

但是它也有好处,比如自带 runtime,比如能够自己控制编译,更方便的编译到小程序,甚至我看到滴滴的 cml 框架直接用标签搞了个多态协议(编译时走指定标记内容)

但是谈到设计,我还是将它归类为无可救药的组件化机制

然后就是 react 的 class 方案,浏览器支持,但也有缺点——

class 其实很难在 1kb 的框架里搞定,主要是 class 有生命周期事件,还有 context 这种重头,而且 class 的拓展形式比较绝望,HOC、render props、extend 等

然后就是 hooks API,它的优点就是复用方便,function 一把锁,而且 API 很魔幻 缺点就比较致命,不能拿到 this 导致很多事情都做不了,也没有多余的字符,搞编译也不可能

要知道,国内的框架,到头来都去搞多端编译了都……

状态更新

框架的另一个要素,状态更新机制,看图

经过投票,可以看到,最终剩下的,就 react 和 vue3 的方案

而我个人,超级喜欢骚的 API,所以自然是选择了 proxy

当然 fre 是 fiber 了,所以其实不是我最喜欢的,但是也没办法,我第一个版本是使用 Proxy 搞的,后来发现,还是和 react 保持一致的好……好抄

但是我确实最喜欢 Proxy 无疑,稍等我再说

vdom diff

单独将 diff 拿出来说::>_<:: 其实我们看到很多框架是没有 diff 的,如 vue1.x,然后就是递归的 diff,如 preact、vue2.x

还有就是 react 的 fiber

其实呢,对于 vue 而言,确实 diff 的必要性不是很大,但是同样的,对于 react 而言,fiber 的必要性也不大(⊙o⊙)…

所以,对于成熟的框架,这种机制只是一种必需品,用来高度抽象的,统一非浏览器环境的

所以如果写一个框架,我觉得还是一定要加一层 vdom 的

优先级调度

不得不提一下 react 的优先级的调度,通俗来说,就是它能摆脱浏览器的堆栈,高优先级任务一定执行,低优先级任务抽空执行

这个调度方案的实现,要么依赖 fiber,要么依赖 runtime

所以其实 react 和 vue 都可以做

但是我不喜欢 vue 的 runtime ,fiber 也一时半刻搞不定

唉,所以 fre 内部目前还是 micro task

总结

综上所述,fre 的各个方案,综合起来看,其实只是拥有了一个完成度还算 ok 的 1kb

hooks API 固然骚,也奈何没办法多端编译,后续发展是个问题

而 vue 的模板我又很不喜欢,我还想搞调度,所以……如果我想写一个理想的框架,大概长这样:

  1. Proxy 的状态更新方案,骚
  2. class 的组件化方案,综合考虑最好的组件化方案
  3. 使用 web-component 作为 runtime,搞调度
  4. 拥有 vdom diff,使用 JSX

以上,是我对新框架的思考,我先不搞了,你们来呀!

最终,放上 fre 的 github 地址:

github.com/132yse/fre

欢迎 star 与 pr ::>_<::