高性能MVVM框架的设计与实现:San
上QQ阅读APP看书,第一时间看更新

San尤其适合前端业务逻辑相对简单的业务。在百度,已有多个产品线把San定为业务首选前端开发框架,相关的业务已服务上亿用户。这足以证明San是可靠、可依赖的前端框架。

San与上文所述的框架之间显然存在一些差异。从本质上说,虽然框架的核心目标都是做出性能更好的Web应用,但每个框架不同的设计思路和理念导致了这样的差异。通常,我们可以从以下几个宏观维度来比较。

如果我们认为原生的JavaScript是最低的抽象程度,那么jQuery这样的老牌框架的抽象程度基本上与其相差无几。只需要了解JavaScript就能上手jQuery是后者在早期具备一定统治力的重要原因。

在随后兴起的组件化框架中,React的抽象程度较低,只需要理解组件(component)、状态(state)、钩子(hook)和JSX就可以上手了。

Angular的抽象概念较多,光上手就需要了解十几个概念,这些概念大部分从一些知名的后端框架演变而来,对于应对一定规模和延续性的产品架构来说是必要的,而对于轻量级的需求实现就显得冗余了。

San、Vue和Svelte基本上处在前两者之间,模板(template)与HTML差异较小,了解完数据(data)、方法(method)和单文件组件就可以上手了。

从这个维度,可以综合看待并比较框架在浏览器内存里执行的任务和在编译阶段做的预处理工作(具体效果如图1-4所示)。

{%}

图1-4 不同框架的RealWorld演示项目的体积大小(KB)

一个极端是重运行时的React,数据变化需要生成新的虚拟DOM,再通过diff算法得出最小操作行为。

另一个极端是重编译、轻运行时的框架,典型代表就是Svelte。它在编译和构建阶段将应用转换为理想的JavaScript应用,而不是在运行阶段解释应用代码。这就意味着不需要为框架消耗额外的性能,同时保证了首屏加载没有额外的消耗。

San和Vue处于中间地位,在运行时和预编译之间做了平衡。它们保留了虚拟DOM,通过响应式控制虚拟DOM的粒度,并结合编译期生成的节点树和其他优化控制变更范围。

此外,San在运行时还具备组件反解的能力。配合服务端渲染,在初始化组件时不使用预设模板渲染视图及创建根元素,就能直接到达compiled(已编译)、created(已创建)和attached(已附加)生命周期阶段,节约了大量客户端渲染时间。

如上所述,Svelte可以做到直接编译成JavaScript,性能接近原生,同时在抽象程度上也接近于San和Vue。为什么San和Vue还要保留虚拟DOM这个额外的运行时损耗呢?比较重要的答案就是跨端支持,这里的“端”除了客户端,也包含服务端。

虚拟DOM除了可以参与diff的计算,也描述了视图本身是怎样的,在跨端领域意义重大。视图层返回了这个对象,渲染层就可以调用不同平台的渲染API去绘制。

San提供了San SSR和San Native两大解决方案,实现了服务端同构与跨平台渲染。这两个方案的基础都是虚拟DOM。

React是经过实践检验的领导者,得到了企业和庞大的开源社区支持。从虚拟DOM到JSX,从不可变性(immutability)到React钩子,React社区提出了很多伟大的革命性想法。React作为一个库而不是框架,其中的许多依赖源于由社区构建和支持的第三方库,无论对于技术选型还是应用开发,都有着极大的灵活性。

Vue在文档和生态运营方面堪称业界典范,作者倾注了相当多的精力去主导和维护生态的建设,官方也给出了很多优秀的解决方案。

围绕San生态的建设一直在进行,目前已经有了San CLI、San DevTools、San SSR和San Native等,周边生态已基本和Vue等业内主流框架对齐,足以满足当前的业务需求(见图1-5)。

{%}

图1-5 San的技术矩阵

目前San与Vue、React等主流框架的生态对比如表1-3所示。

表1-3 San与Vue、React等主流框架的生态对比

一个成熟框架的外围生态必然包括开发、构建、调试、部署相关的工具链。不管是工具链还是跨端开发方案,都和框架本身的设计密切相关,第6章~第9章会具体介绍,并且说明San作为基础是如何支撑这些上层建筑的。