为了进一步提升小程序的渲染性能和体验,我们推出了一套新渲染引擎 Skyline,现在,跟随着基础库 3.0.0 发布 Skyline 正式版。
我们知道,小程序一直用 WebView 来渲染界面,因其有不错的兼容性和丰富的特性,且各大厂商也在不断优化 Web 的渲染性能,但 Web 体系相比于原生开发,在性能上仍然有较大差距,并且特性上发展缓慢,使得小程序很难做出类原生的体验。因此,我们开发了一套新渲染引擎 Skyline,旨在替代 WebView 作为小程序的渲染层,以提供更优秀的渲染性能和诸多增强特性,让小程序能达到原生的体验。
以下为你全方位介绍 Skyline 的特点。
提供更好的性能
在渲染流程上,WebView 因其需要向后兼容,积累了较多历史包袱,加之整体设计目标不同,使其渲染流水线更加冗长复杂,而 Skyline 则更为精简,同时只保留更现代的 CSS 特性。在此基础上,我们还进一步实现了很多优化点:
- 单线程版本组件框架。Skyline 下默认启用了新版本的组件框架 glass-easel,该版本适应了 Skyline 的单线程模型,使得建树流程的耗时有效降低(优化 30%-40%),同时 setData 调用也不再有通信开销。
- 组件下沉。我们将部分内置组件(如 scroll-view、swiper、picker-view 等)直接在底层实现,以追求更流畅的交互体验。此外,我们也将常用的内置组件(view、text、image)从 JS 下沉到原生实现,相当于原生 DOM 节点,有效降低了创建组件的开销(优化 30%)。
- 长列表按需渲染。长列表是一个常用的但又经常遇到性能瓶颈的场景,Skyline 对其做了一些优化,使 scroll-view 组件只渲染在屏节点(用法上有一定的约束),并且增加 lazy mount 机制优化首次渲染长列表的性能,后续我们也计划在组件框架层面进一步支持 scroll-view 的可回收机制,以更大程度降低创建节点的开销。
- WXSS 预编译。同 WebView 传输 WXSS 文本不同,Skyline 在后台构建小程序代码包时会将 WXSS 预编译为二进制文件,在运行时直接读取二进制文件获得样式表结构,避免了运行时解析的开销(预编译较运行时解析快 5 倍以上)。
- 样式计算更快。Skyline 通过精简 WXSS 特性大幅简化了样式计算的流程。同时 Skyline 与小程序框架结合也更为紧密,例如: Skyline 结合组件系统实现了 WXSS 样式隔离、基于 wx:for 实现了节点样式共享(相比于 WebView 推测式样式共享更为精确、高效)。
- 降低内存占用。在 WebView 渲染模式下,一个小程序页面对应一个 WebView 实例,并且每个页面会重复注入一些公共资源。而 Skyline 只有 AppService 线程,且多个 Skyline 页面会运行在同一个渲染引擎实例下,因此页面占用内存能够降低很多,还能做到更细粒度的页面间资源共享(如全局样式、公共代码、缓存资源等)。
总体上,由于 Skyline 在渲染流程上更加可控,我们能让小程序的特性尽可能融合进渲染流程中完成,还有很多在细节上的优化(比如对 rpx 的处理、image mode=widthFix 的处理等,都是融入渲染流程中,而避免在 JS 做太多额外的计算)就不再一一介绍。另外,我们也在持续优化中,Skyline 会是之后小程序性能优化的重点。
至于目前整体的性能情况,我们从已上线的小程序数据观测到(基础库 3.0.0 glass-easel 带来的优化暂未体现),启动耗时方面,即点击到完全渲染(LCP)的耗时,WebView 对比 Skyline 为 2492ms vs 2052ms,减少 17.6%;渲染阶段耗时方面,即框架建树到完全渲染(LCP)的耗时,WebView 对比 Skyline 为 626ms vs 312ms,减少 50%。
根除旧有架构的问题
在基于 Web 体系的架构下,小程序的部分基础体验会受限于 WebView 提供的能力(特别是 iOS WKWebView 限制更大一些),使得一些技术方案无法做得很完美,留下一些潜在的问题。
- 原生组件同层渲染更稳定。iOS 下原生组件同层渲染的原理先前有介绍过,本质上是在 WKWebView 黑盒下一种取巧的实现方式,并不能完美融合到 WKWebView 的渲染流程,因此很容易在一些特殊的样式发生变化后,同层渲染会失效,而在 Skyline 下可以很好地融合到渲染流程中,因此会更稳定。
- 无需页面恢复机制。iOS 下 WKWebView 会受系统的管理,当内存紧张时,系统就会将不在屏的 WKWebView 回收,会使得小程序除前台以外的页面丢失,虽然在页面返回时,我们对页面做了恢复,但页面的状态并不能 100% 还原,而在 Skyline 下则不再有该问题。
- 无页面栈层数限制。由于 WebView 的内存占用较大,页面层级最多有 10 层,而 Skyline 在内存方面更有优势,因此在连续 Skyline 页面跳转(复用同一引擎实例)的情况下,不再有该限制。
全新的交互动画体系
我们发现,要达到类原生的体验,渲染性能与交互动画缺一不可,渲染性能能让页面更快渲染出来,而交互动画能让浏览页面的体验更佳。但在 Web 体系下,难以做到像素级可控,交互动画衔接不顺畅,究其原因,在于缺失了一些重要的能力,为此,我们提供一套全新的交互动画能力。
- Worklet 动画机制。在原来双线程的架构下,若要对界面元素做逐帧动画是需要频繁在逻辑层和渲染层之间通信的,这会带来较大的延迟,动画也就不会流畅。而 Worklet 动画正是为了解决这类问题而诞生的,其运行机制与 WXS 类似,但比 WXS 更靠近渲染流程而性能更好,而且支持的特性更多,可扩展性更强,这个是 Skyline 交互动画体系的基础。
- 手势系统。在原生的交互动画里,手势识别与协商是一个很重要的特性,而这块在 Web 体系是缺失的,因此 Skyline 下补全手势系统相关特性,包括常用手势的识别,如缩放、拖动、双击等,还有很重要的手势协商机制,在遇到手势冲突(常见于滚动容器下)时决定让哪个手势生效,以实现更顺畅的动画衔接。
- 自定义路由与共享元素。页面间的自定义转场动画,在原生应用里也是一个很常见的交互动画。在原来的小程序架构下,每个页面都是独立的 WebView 渲染,互相隔离,其跨页能力是基本不具备的。因此,Skyline 提供了一套自定义路由机制,能实现市面上大多数页面转场动画,同时也提供了共享元素机制,能很方便地做到同一元素在页面间飞跃的效果。
此外,对内置组件的扩展也是重要一环,特别是 scroll-view 组件,我们优化了下拉刷新的体验,并且实现“下拉二楼”的交互,也添加很多控制能力,这都是些在 Web 下很难做到又非常重要的特性。总之,这套全新的交互动画体系是 Skyline 能实现类原生交互体验的关键。
释放更多高级能力
除了上面提到的交互动画能力外,Skyline 所能释放的能力还远不止于此,借助 Skyline 的特点,我们还提供以下新的组件
- grid-view 瀑布流组件。瀑布流是一种常用的列表布局方式,得益于 Skyline 在布局过程中的可控性,我们直接在底层实现并提供出来,渲染性能要比 WebView 更优。
- snapshot 截图组件。大多数小程序都会基于 canvas 实现自定义分享图的功能,但分享图的布局较复杂时,canvas 的方案实现成本会更大,而 Skyline 是具备对 WXML 子树截图的能力的,因此我们直接封装后开放出来,这样能复用更完善的 WXSS 能力,极大降低开发成本。
除了新增的组件,还有不少是原有内置组件扩展的小特性,这里就不一一介绍,可 查看文档 或 更新日志。未来,我们还会持续在 Skyline 上开放更多高级功能,如全局跨页面组件,scroll-view 列表节点 builder 模块支持节点可回收等,更多可查看 文档特性状态 一栏,同时,也欢迎开发者在社区给我们提议。
至此,Skyline 的主要特点已基本介绍完毕,更完整的介绍、用法、迁移指引、注意点等等请查阅 文档。建议开发者现在就使用起来,尽早享受到 Skyline 带来的优化和丰富的特性,如果开发中遇到问题,可在开发者社区发贴反馈,我们也会邀请加入沟通交流群。