halo,大家好,我是 132,今天给大家带来一篇框架设计的总结文章
首先庆祝 fre 已经一岁啦,在过去的一年里,star 终于过千了,在 2019开源中国评选 中排名第八
然后就……现在 fre 也完成了接近 100% 的测试覆盖率,已经处于稳定期了
所以总的来说,现在是时候做个总结了,然后顺便预测一下接下来的方向
组件化方案
为什么要将 组件化方案 放到第一个要谈的点,因为今年 react hooks 和 vue composition 的出现,使得前端框架的组件化方案彻底从 class 蜕变为 function
起初,react 的组件化方案是 class
class HelloMessage extends Framework.Component {
render() {
return <div>Hello world</div>;
}
}
class 的方案主宰了很多年,直到现在还有一些新框架,如 omi,stencil,angular,在框架最初就选择了 class
它的好处是,主要是这几个方面:
- 贴合 web component,符合 web component 默认范式
- 方便往 this 上挂东西,比如挂 scoped css
- HOC,render props 等都不是很灵活,样板代码更适合做编译多端(如 taro,nanachi)
它的坏处:
- 不是很需要 web component
- 不是很需要编译跨端(如 fard,kbone,taro-next)
- 不是很需要 this,super,extend,组合优于继承
综上所述,class 的优缺点都有,但是对于今年来说,很明显 class 的优点大家已经不在意了,事实上除非你写的是 web component 框架,不然 class 没什么好的
然后,今年的大成就是 function 组件,hooks 和 composition,他们的共同好处是逻辑复用,共同缺点是由于方便了逻辑复用,导致会写出很多面条代码,难维护
我们先说 composition,它长得这样
import { h, ref, reactive } from 'vue'
export default {
setup() {
const count = ref(0)
const object = reactive({ foo: 'bar' })
return () => <div>
{count}{object.foo}
</div>
}
}
我们看到,劫持两个变量,然后返回一个闭包,这样做的好处
- 返回闭包,变量不需要每次都初始化
- 不需要 memo,deps 等心智负担
坏处是
- 需要 ref 和 reactive 两个 API
- render function 必须是 plan function
- 闭包陷阱
以上,composition API 并不是和 vue 官方文档一样,只有好处没有坏处,以后用于生产,问题会慢慢暴露出来
然后说 react hooks / fre hooks
import { h, render, useState } from 'fre'
function App() {
const [count, setCount] = useState(0)
return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}
如上,直接返回 vdom,而不是显式返回闭包
这么做的坏处:
- memo 和 deps 的心智负担
- 变量频繁初始化,如果变量是个 heavy value,那么会阻塞组件
这么做的好处是
- 有利于 concurrent 和 Suspense
- API 好看
综上,其实 hooks 的缺点也不多,说白了就一个——心理负担 但是一旦你熟悉了 deps 的规则,你就会得心应手
以上,是今年关于组件化的总结,总的来说就是,前端框架今年还是 function 为主,彼此都有好处和坏处,大家随便选一个即可
视图更新
这是今天我想说的第二个点,也就是 UI 的更新,这也是我今年下半年做的事情
- exact updating vs top-down updating
精确更新和自上而下的更新,精确更新首先是 vue 提出来并给出实现的,它的本质是浅比较 props,来判断是否需要 update
我觉得这个可以接受,但是……fre 团队大部分人都非常排斥这个,他们一致认为 vue 的做法是不可接受的
我也很绝望,我现在期望能够找到一个更好的方案,令人普遍接受的方案
但是说实话我很喜欢精确更新,因为这样一来,可以从很大程度上减少 hooks 的重复初始化
- 异步更新
目前 vue,preact 等框架的异步更新就是一个简单的微任务,没有其他任何处理
fre 的异步更新是时间切片,它的本质是使用 while 循环链表,然后任务可以在 dom 操作之后的宏任务中执行(相当于空闲时间)
时间切片只是其中一个方法,用于减少 UI 的阻塞,也是目前粒度最小的方法
针对 vue 这种,更新和dom操作无法拆,更新也无法拆的框架,还有另一个方案
我把它叫做双队列更新,原理是排队论,如果你前面排队的人耗时时间太长,那就去旁边等着,先让后边的来,别碍事
综上所述,异步更新无非就两种模式,精确更新和上下更新,更新队列目前最好的两种,fiber架构下的时间切片和普通架构下的双队列排队
其他
除了组件化和试图更新,其他方面,如vdom和template,mutable和immutable,这些今年都没有什么新东西,我就不说了……
最后,来说说 fre2
因为说实话,现在 fre1 已经完全稳定了,而目前 fre 比 react 就缺了 Suspense
所以 fre2 大概是这样:
- 改用 typescript
- Suspense
- useTransition
- 重构更新队列
我也需要新的点子,所以招人啊招人,招人一起贡献新点子!
issue 大门时刻为你打开!