9月23日,"掘力计划"第25期沙龙活动在北京举行。本期活动的主题为"性能专场",旨在探讨前端性能优化的实践方案。活动邀请到 DCloud 公司 CTO 崔红保进行题为《跨端框架的性能优化实践》的技术分享。
崔红保讲师是移动开发领域的老兵,有着十多年的丰富经验。他见证了移动软件开发从 J2ME、Symbian、BlackBerry 到 iOS、Android、小程序等多个时代的演进。目前他担任 DCloud 公司 CTO 一职,同时负责 uni-app 跨端框架的产品规划与技术创新。本次分享的主要内容包括:跨端框架的选型策略、性能优化的痛点分析、UTS 编译方案介绍、未来的开发模式展望等。
第一部分:跨端框架的选型指南
选择跨端框架时,需要从多个维度考量。首先是功能维度,要考虑业务需要兼容的平台,比如微信小程序、抖音小程序等不同的小程序,是否需要打包成 App 进行发布,是否需要发布到 H5 或 PC 端等。特别是如果有发布 App 的需求,则需要考虑 App 中是否需要调用原生能力,比如支付、分享、地图导航等,以及团队是否有能力处理相关的原生 SDK 集成工作。
其次是扩展性维度。每个平台都有自己的特有能力,而跨端框架未必都有集成这些能力。因此需要考虑框架是否易于扩展到新的平台,如果新增小红书小程序等新平台,框架是否可以自助扩展。
再次是性能维度。相比原生开发,跨端框架为兼容各平台,会增加许多补丁代码,是否会导致性能下降,特别是一些常见的性能卡点,如长列表、手势操作等场景下的性能。
此外,还要考量 DSL 生态问题。选择什么语言及其生态,要根据团队技术栈来决定。一个门槛较高的语言,其社区资源较少,不一定适合。
最后一个考量点是开发体验。框架是否支持调试、热重载等能力,如果出现错误,是否可以快速定位源码问题等。
第二部分:跨端框架的性能优化
跨端框架的性能优化一直是业界关注的难点。目前主流的 Hybrid 框架存在一些共性的性能痛点。首先是 Web 渲染层本身的问题,包括页面切换时的白屏问题,以及各类手势交互时的卡顿,比如地图的拖拽、视频的快进等操作。这是由于每次页面切换时,Web 需要重新加载资源;另外在频繁的手势交互中,繁重的重绘重排也会影响流畅度。
为解决 Web 渲染的问题,很多框架会引入原生组件,比如使用原生实现的导航栏、选项卡、视频播放器等,这可以避免白屏问题,也可以利用原生组件的性能优势。但是原生组件的引入也带来了新的问题,包括原生组件与 Web 内容的层级关系导致的各种 visual 问题,以及原生组件与 Web 内容频繁通信导致的性能损耗等。
接下来的优化思路包括同层渲染、BindingX 等,目的是减少视图层和逻辑层之间的通信次数。但由于逻辑层和渲染层本身是两个隔离的环境,它们之间始终需要通信协调,这决定了与真正的原生开发相比,总会有一定的性能损耗。
因此,要真正实现媲美原生的性能,必须解决根本问题,即逻辑层和渲染层必须在同一个环境中,不再存在隔离和通信问题。UTS 框架的设计思路就是消除逻辑层的JS运行时,直接通过编译的方式生成逻辑代码和 UI 代码,实现它们在一个主进程中运行,以解决这个根本性的通信问题。
第三部分:UTS - 实现与原生媲美的跨端框架
UTS 使用 TS 和 Vue 进行开发,编译成原生语言,实现媲美原生的性能:
-
前端使用 TS 和 Vue开发,在Web平台和小程序平台编译成 JS
-
在原生平台,翻译成 Kotlin、Swift 等语言
-
原生平台,使用自研的Native Vue Runtime 实现数据响应
UTS 跨端框架通过编译的方式,实现了前端代码可以编译成多端原生代码的能力。在开发阶段,UTS 使用 TypeScript 和 Vue 作为开发语言。这保持了它作为跨平台框架的特性,开发者可以用 Web 开发的方式进行开发。
编译阶段,UTS 会把 TypeScript 和 Vue 代码,编译成目标平台的原生语言。例如在 iOS 上,代码会被编译成 Swift;在 Android 平台,代码会被编译成 Kotlin。编译器需要处理 TypeScript 和目标语言在语法上的差异。例如变量定义、条件语句、循环语句、类定义等在不同语言中的语法都不太一样,编译器需要进行转换。
另外,为了保证前端的数据响应功能可以在编译后的原生代码中正常工作,UTS 实现了一套 Native Vue Runtime。这套运行时框架提供了类似 Vue 的数据响应能力,可以运行在诸如 Kotlin、Swift 等语言环境下。
通过编译和运行时的设计,UTS 实现了以Web形式开发,编译成原生语言,运行性能接近原生的开发框架。它解决了当前跨端框架中,JS 引擎作为中间层导致的性能问题。
第四部分:基于高性能跨端框架的云端一体开发
基于高性能跨端框架的云端一体开发,可以实现更加高效的开发方式。与传统的前后端分离开发相比,云端一体开发可以减少前后端之间的协调沟通成本。前端工程师在完成UI层面的工作后,可以直接调用云函数,操作云数据库,无需等待后端接口联调。这种开发方式提高了开发效率。
以前端页面为例,使用传统开发方式实现一个图文列表页面,需要编写后端的数据库查询逻辑,发起 Ajax 请求获取数据,再用前端框架渲染。整个页面代码量至少在 90 行左右。而使用云端一体组件之后,可以直接在前端组件中查询云数据库,然后传递到列表组件渲染,整个页面的代码量可以减少到约 30 行,至少节省 60% 的代码量。
此外,云端一体开发还可以简化前后端交互方式。以往通过 Ajax 请求云函数,需要传递 URL、请求数据,处理成功和失败回调等。现在可以通过 import 的方式,直接引入云函数(云对象),然后像调用本地模块一样调用它的方法,无需处理大量 Ajax 请求相关代码。
最后,云端一体组件也改变了前端组件的生态。以前的前后端完全割裂,需要分别选择适合各自技术栈的前后端组件,现在可以直接获取同时包含前后端功能的插件,极大地提升了开发效率。
总结
本次分享,崔红保讲师首先讲解了评估跨端框架的维度,然后剖析了跨端框架的性能痛点所在,进而提出了消灭 JS 进程、编译生成原生代码的解决方案,最后展望了云端一体开发带来的编程模式升级和效率提升。
可以看出,性能和开发效率是衡量跨端框架的两个关键指标。随着新技术的引入,跨端框架正在朝着超越原生应用的方向持续发展。