【前端百题斩】小程序,11个模块、300+面试真题,助力进大厂、拿高薪。
最近,华为开源了一款前端框架 —— openInula[1]。根据官网提供的信息,这款框架有3大核心能力:
响应式API
![f2260b565f4693d4a73d6f76ebe3866b.png](https://i-blog.csdnimg.cn/blog_migrate/86b581bd72e0af5af3185a48ace5ae18.png)
兼容
React
API
![b7e762c93d5ac9306853b8423a1b4c84.png](https://i-blog.csdnimg.cn/blog_migrate/c61f3a7480c30b25cab5bd758ec51a80.png)
官方提供6大核心组件
![b1ac1e370ea3c416d47c3bf78b97e2c2.png](https://i-blog.csdnimg.cn/blog_migrate/b4a16c7fd9b5f4657465fd54c3234af7.png)
并且,在官方宣传视频里提到 —— 这是款「大模型驱动」的「智能框架」。
那么,这究竟是款什么样的前端框架呢?我在第一时间体验了Demo
,阅读了框架源码,并采访了框架核心开发者。本文将包括两部分内容:
对框架核心开发者陈超涛的采访
卡颂作为一个老前端,阅读框架源码后的一些分析
采访核心开发者
开发Inula
的初衷是?
回答:
华为内部对于业务中强依赖的软件,考虑到竞争力,,会开发一个内部使用的版本。
Inula
在华为内部,从立项到现在两年多,基本替换了公司内绝大部分React
项目。
卡颂补充背景知识:
Inula
兼容React
95% API,最初开发的目的就是为了替换华为内部使用的React
。为了方便理解,你可以将Inula
类比于华为内部的React
为什么开源?
回答:
华为对于「自研软件」的公司策略,只要是公司内部做的,觉得还ok的自研都会开源。
接下来的提问涉及到官网宣传的内容
宣传片提到的大模型赋能、智能框架是什么意思?
回答:
这主要是Inula
团队与其他外部团队在AI
、低代码
方向的一些探索。比如:
团队与上海交大的一个团队在探索「大模型赋能chrome调试业务代码」方面有些合作,目的是为了「自动定位问题」
团队与华为内部的「大模型编辑器」团队合作,探索「框架与编辑器定制」可能性
以上还都属于探索阶段。
Inula未来有明确的发展方向么?
回答:
团队正在探索引入「响应式API」,相比于「React的虚拟DOM」方案,响应式API
能够提高运行时性能。24年可能会从Vue
composition API
中寻求些借鉴。
新的发展方向会在项目仓库以RFC
的形式展开。
补充:
RFC
是「Request for Comments」的缩写。这是一种协作模式,通常用于提出新的特性、规范或者改变现有的一些规则。RFC
的目的是收集不同的意见和反馈,以便在最终确定一个决策前,考虑尽可能多的观点和影响。
为什么要自研核心组件而不用社区成熟方案?
卡颂补充:所谓「核心组件」,是指状态管理、路由、国际化、请求库、脚手架这样的框架生态相关的库。既然
Inula
兼容React
,为什么不直接用React
生态的成熟产品,而要自研呢?毕竟,这些库是没有软件风险的。
![a6d23d1da4c5c2fa6273d57cf89db851.png](https://i-blog.csdnimg.cn/blog_migrate/c9d54e3fabc7e457c9d9fcea45e74119.png)
回答:
主要还是丰富Inula
生态,根据社区优秀的库总结一套Inula
官方推荐的最佳实践。至于开发者怎么选择,我们并不强求。
卡颂的分析
以上是我对Inula
核心开发者陈超涛的采访。下面是我看了Inula
源码后的一些分析。
要分析一款前端框架,最重要的是明白他是如何更新视图的?这里我选择了两种触发时机来分析:
首次渲染
触发的方式类似如下:
Inula.render(<App />, document.getElementById("root"));
执行
useState
的更新方法触发更新
触发的方式类似如下:
function App() {
const [num, update] = useState(0);
// 触发更新
update(xxx);
// ...
}
顺着调用栈往下看,他们都会执行两步操作:
创建名为
update
的数据结构执行
launchUpdateFromVNode
方法
比如这是首屏渲染时:
![9b0d59d9d114c1e78388ac792e9e58bd.png](https://i-blog.csdnimg.cn/blog_migrate/8ddd1c736b10747f727873a8ec924271.png)
这是useState
更新方法执行时:
![2b7cd238251e87fd6e607e705cdf5a6e.png](https://i-blog.csdnimg.cn/blog_migrate/effc330cc5fda32d06c9902b37166b7c.png)
launchUpdateFromVNode
方法会向上遍历到根结点(源码中遍历的节点叫VNode
),再从根节点开始遍历树。由此可以判断,Inula
的更新机制与React
类似。
所有主流框架在触发更新后,都不会立刻执行更新,中间还有个调度流程。这个流程的存在是为了解决:
哪些更新应该被优先执行?
是否有些更新是冗余的,需要合并在一块执行?
在Vue
中,更新会在微任务中被调度并统一执行,在React
中,同时存在微任务(promise
)与宏任务(MessageChannel
)的调度模式。
在Inula
中,存在宏任务的调度模式 —— 当宿主环境支持MessageChannel
时会使用它,不支持则使用setTimeout
调度:
![ececfa8954e75df067e89d014c25c5d3.png](https://i-blog.csdnimg.cn/blog_migrate/41146f919a9b3c33b0c3e7a29770f357.png)
同时,与这套调度机制配套的还有个简单的优先级算法 —— 存在两种优先级,其中:
ImmediatePriority
:对应正常情况触发的更新NormalPriority
:对应useEffect
回调
每个更新会根据「更新的ID」(一个自增的数字)+ 「优先级对应的数字」 作为优先级队列中的排序依据,按顺序执行。
假设先后触发2次更新,优先级分别是ImmediatePriority
与NormalPriority
,那么他们的排序依据分别是:
100(假设当前ID到100了)- 1(
ImmediatePriority
对应-1
) = 99101(100自增到101)+ 10000(
NormalPriority
对应10000
)= 10101
99 < 10101,所以前者会先执行。
需要注意的是,Inula
中对更新优先级的控制粒度没有React
并发更新细,比如对于如下代码:
useEffect(function cb() {
update(xxx);
update(yyy);
})
在React
中,控制的是每个update
对应优先级。在Inula
中,控制的是cb
回调函数与其他「更新所在回调函数」之间的执行顺序。
这意味着本质来说,Inula
中触发的所有更新都是「同步更新」,不存在React
并发更新中「高优先级更新打断低优先级更新」的情况。
这也解释了为什么Inula
兼容 95% 的React
API,剩下 5% 就是「并发更新相关API」(比如useTransition
、useDeferredvalue
)。
现在我们已经知道Inula
的更新方式类似React
,那么官网提到的「响应式API」该如何实现呢?这里存在三条路径:
一套外挂的响应式系统,类似
React
与Mobx
的关系内部同时存在两套更新系统(当前一套,响应式一套),调用不同的
API
使用不同的系统重构内部系统为响应式系统,通过编译手段,使所有
API
(包括当前的React API
与未来的类 Vue Composition API
)都走这套系统
![3b03aa400c573ed686fb2556d9006db8.png](https://i-blog.csdnimg.cn/blog_migrate/199a31cded2e6be70f3c2cc74dc9825a.png)
其中第一条路径比较简单,第二条路径应该还没框架使用,第三条路径想象空间最大。不知道Inula
未来会如何发展。
总结
当前,Inula
是一款「类React的框架」,功能上可以类比为「React并发更新之前的版本」。
下一步,Inula
会引入「响应式API」,目的是提高渲染效率。
对于未来的发展,主要围绕在:
探索
类 Vue Composition API
的可能性迭代官方核心生态库
对于华为出的这款前端框架,你怎么看?
参考资料
[1]
openInula: https://www.openinula.net/