作者:孙然(煮虾)

对于小程序技术来说,容器加载和前端异步渲染的过程中固然不可避免的会有白屏或 loading 页的展示,短则一瞬间,长则需要数秒才能展示首屏。如果白屏时间长,将非常影响用户的体验。根据 Google 的统计,如果页面加载耗时超过了 3s,那么有 53% 的用户会选择直接退出该页面了。

为加速小程序首页的展示,支付宝和手淘运用了基于 HTML 的快照技术,主要思路都是缓存首页 HTML 供下次启动时与数据一起优先渲染以提前首屏展示的时间,适用于传统 WebView 渲染的小程序场景。这种基于 HTML 的快照技术能够极大缩短启动时的白屏时间,但首屏展示的速度还是不够快,期间用户仍然会有可见的白屏感受。并且快照展示的仍然是无法点击操作的页面,需要等待 JS 部分 ready 后才可点击交互。

为了追求极致的体验效果,我们提出了一种全新的小程序快照技术,目标是既做到彻底消除白屏现象,同时也要能够响应用户交互。

核心思路

不同于现有的基于 HTML 的快照技术,我们提出了一种 native 的图像级别的快照技术,主要由以下三个步骤:

  • 步骤1:在小程序启动后合适的时机将小程序首页保存为图片,我们称之为快照
  • 步骤2:下次打开小程序时先展示上次保存的快照,再启动小程序
  • 步骤3:当小程序启动完后的合适时机,隐藏快照,展示出真实的小程序首页,并保存当前界面视图作为下次的快照(同步骤1)

效果

现在钉钉中的新建 DING 日程页面就运用了快照技术,前后效果对比如下:

before after

可以看出,通过快照技术,该页面实现了首屏秒开的效果,启动白屏的现象彻底消失,页面的首屏渲染耗时从 1700ms 左右降低到了 300ms 以下。

下面我会对快照技术的几个关键考虑点进行详细介绍。

场景和时机

理想中的快照,应当是能够和首屏页面完全重合,并且在快照隐藏时不会产生任何视觉变化的。那么生成快照的时机和运用快照的场景就直接决定了快照技术能够达到的优化效果。

什么页面适合用快照?

并不是所有的小程序都适合使用快照技术来提升首屏体验。如果使用不当,快照可能还会成为体验的减分项。为达到最佳效果,一般首屏页面满足下面几个条件是比较适合使用快照的:

  • 首屏页面较为固定。如果首屏不固定,很难找到合适的快照时机来保证快照与下次的首屏重合
  • 首屏页面不含用户隐私数据。用户的隐私数据不应当被快照下来

什么时候生成快照?

如果快照的时机过早,快照可能展示的也是白屏或者未渲染完整的首页框架。

如果快照的时机过晚,可能用户已经对首屏有了交互(滚动、点击等),容易生成无法和首屏重合的快照。

所以需要根据不同的首屏场景来确定最佳的快照时机。一般我们考虑快照的时机有:

  • 小程序首屏 Page 的 onReady 生命周期回调里。但此时页面很可能仍然没有渲染完成,可以考虑适当延时后进行快照
  • 小程序首屏的数据如果需要远程拉取,可以在远程获取到首屏数据后进行
  • 用户发生滚动时、点击等交互后不再进行快照

什么时候隐藏快照?

我们一般考虑在生成快照时去隐藏当前已经展示的快照。二者的顺序一般是在隐藏快照后立即生成快照,才能实现快照和真实页面的无缝衔接。

当然,也需要考虑小程序启动可能失败的场景。这里需要对展示快照的时间设置一个展示的上限,如果展示时间达到上限时小程序首屏仍然没有启动成功,那么快照将直接隐藏,以防造成首屏对用户可见但一直不响应的尴尬局面。

这里我们在还隐藏快照时做了一个小小的视觉优化。考虑到在隐藏快照时,如果直接隐藏快照,一旦快照和真实页面稍有差别,在视觉上可能就会有闪烁的体感发生。

所以在隐藏快照时,我们会做一个 200ms 的淡出动画,来缓解这种快照和真实页面差异导致的闪烁感。因为有时快照的时机可能会稍提前于首页网络数据加载成功、图片加载成功等这些异步事件成功的时机,导致快照比真实页面元素缺少或者数据不准确,而淡出动画能够有效淡化这些差错造成的视觉异常感。下面的 demo 对比了这两种情况:

直出 淡出

可交互

由于快照和真实的首屏页面基本是相同的,从用户体感上用户会以为首屏已经成功展现,也应该是个可交互的页面。所以单纯展示死的快照页面是远远不够的,做到可交互是我们快照的重要能力

我们的快照支持响应用户的点击行为,具体方法就是在用户点击快照时先暂存用户的点击事件,待快照隐藏时将此次事件分发到真实页面上去。

此过程中如果用户有多次点击事件,我们只会响应最后一次点击事件。

从用户体感上来说,可能用户会感觉到此次点击的响应会比较慢,但不会让用户感知到它点击的是快照还是真实首页。

如果是小程序启动较慢的场景,还可以考虑在用户点击后展示 loading:

为进一步提高快照层的可交互性,我们甚至还可以允许开发者设定一些快照层的点击区域和简单操作,使用户在点击快照层的时候快速响应点击事件。例如钉钉的工作台就非常适合这种场景:工作台中的各个应用一般不会频繁变化,并且有很明确的分块区域:

可以配置好不同的点击区域以及对应的 action (例如:跳转到其它页面/应用),形如:

[{area: {left: 100, top: 100, width: 100, height: 100},action: {type: 'openLink', params: { url: 'http://xxx' }}
}, ...]

这样用户在点击快照指定区域时就能直接实现跳转,而无需等待到小程序启动完成。

存储与安全

快照属于敏感数据,并且只保存在客户端本地不能进行上传,管理其存储必须格外小心,否则很容易酿成一起公关事件。

对于快照的存储,我们考虑了以下几点:

加密存储

快照数据必须进行加密存储,这里加密方式用的是集团无线保镖里的加密方法。

隐私保护

快照里不能含有用户的隐私数据。也就是说,快照应当只含有一些 UI 元素或者无意义的默认数据,而不应该含有用户隐私数据。

不含用户隐私数据 含用户隐私数据

那么如何做到获取到不含用户隐私数据的首页快照呢?可以考虑在前端从网络、缓存中获取数据之前进行快照。但这样的快照必定是不完整的,会损失一定的体验,这也是我们不推荐在有用户数据的首屏场景使用快照的原因。

快照清理

快照被存储在客户端中,需要有存储上限。当快照数据达到一定量后,需要淘汰一些老的快照数据。其次,在小程序版本更新、用户登出切换用户时都应该考虑将现存的对应快照数据清理掉。

准确性

当快照上线后,我们需要对快照的用户体验进行感知。最佳的体验是用户根本就没有感知到快照的存在,也就是快照和真实页面完全重合;而如果快照和真实页面相差较大,则会让用户体验大大下降,这是我们需要感知到的。

这里我们主要关注快照的准确性指标,也就是快照和真实页面的相似(重合)程度。准确性越高,则说明快照与真实页面的过渡约自然,体验越好;反之不但不会提升体验,可能还会对用户带来困惑。

如何判断快照准确性

在每次生成快照时,我们会将本次快照与上一次快照进行对比,得出量化的指标进而反映快照的准确性。那么下一步的问题就变成了如何判断两张图片的相似度了。

这里可能首先会想到直接使用像素逐个对比的方式来计算出两张快照中不同像素点的比例,比例越高则快照越准确,但实际上这种方法无法体现出真正的相似度和用户的体感。例如,当两张快照位置只要稍有偏移,得出来的相似度值可能很低;或者是两张色差很小的快照,也可能得到很差的结果。并且,快照的像素数可能达到上百万量级,测试发现逐个的像素对比工作一次可能就会耗时数秒钟。

我们现在使用了 Google 以图搜图中用到的“感知哈希算法”来量化快照的准确性。算法本身流程大致是将图片压缩后得出一些“指纹”信息,然后通过对比不同图片的指纹信息计算出“差异指数”。差异指数越高,则说明二者相似度越低。此算法能够体现出两次快照的相似程度,并且其效率比像素逐个比对的方法有了极大提升,线上数据统计到整个算法的耗时不超过 3ms。

我们对一些场景进行了实验并得出差异指数。可以看出,对于微小字符改变的场景,差异指数非常低;而有明显视觉差距的场景中,差异指数会变高。这样得出的量化值能够体现快照对用户带来的真实体感的影响。

场景差异指数视觉效果

少量字符变化

1

整体偏移

6

如何复原错误快照场景

能够感知快照的准确性后,对于准确性较差的快照,我们还需要知道快照和真实页面相差在什么地方,进而改进快照的时机。

这里,我们是通过获取快照时前端页面 DOM 树的方式来追查当前的真实页面情况。具体操作是在生成快照时获取当前小程序 HTML 页面脱敏后的 DOM 树信息,然后再依赖小程序框架的 CSS 文件,最后直接用浏览器就可以恢复出快照时的界面了

其它能力

局部快照

快照的一个比较大的局限性就是无法适应多变的首屏场景,这种场景使用快照很容易导致每次快照都无法跟真实首页重合,反而降低了用户体验。所以我们考虑提供一种能力,只对首页中每次都基本不变的部分进行快照,而其它多变的部分不进行快照,这样也能够每次使首屏部分内容实现秒出。

例如钉钉里的人脉首页,上半部分是相对固定的展示,而下半部分 feed 流可能每次打开都会展示不同的信息。那么在这种场景下我们就没必要每次都对整个首页第一屏进行快照,可以指定一定高度的部分进行快照,让首页的一部分实现秒出。

超一屏快照

当首页可滚动时,我们甚至可以考虑超过一屏长度的快照,并且下次小程序启动时展示快照时让快照可滚动。此方案需要注意两个问题:

  1. 快照大小
    线上统计显示,一屏的快照文件平均大小在 100K 左右。如果是超一屏的快照,大小可能会达到几百 K。需要在生成快照时预估一个长度上限或快照大小上限,以防快照使用时在低端机中出现 OOM 等异常情况。
  2. 快照滚动
    如果快照在展示时用户进行了滚动操作,那么在隐藏快照时需要记录当前滚动的偏移量,以便将真实首页也滚动到指定位置,才能让快照和真实页面重合。

性能

对于快照的性能表现,我们进行了实验室测试和线上的数据统计。

实验室测试中我们构造了一个超大的快照(5.2M)的极限场景,并在低端机上与正常快照进行了对比:

普通场景极端场景

快照大小

262K

5.2M

内存占用

1840K

3245K

加载视觉体验

直接出现

有极短暂延时

快照加载过程并没有影响正常的页面切换,只是在过大快照的加载可能有短暂的延时。

线上数据显示,带快照的页面加载耗时在 280ms 左右,快照的平均大小约 110K。

快照的生成和准确性检测等工作都是在异步线程中进行的,此时用户交互并未开始,并且在用户滚动、交互后不会进行快照,不会对性能造成太多影响。

这里还有个比较有趣的数据:用户对快照的平均点击次数是 0.6 次,首次点击时间约为 1500ms。也就是说,当快照展示 1.5s 后,有一半多的人会开始首次的交互。这也足矣说明让快照具备可交互能力的重要性。

展望

快照技术虽然缘起是为解决小程序启动性能问题,但实际运用场景可以扩展到更多地方。

理论上来说,任何形式的异步渲染场景,不论是现在 WebView 还是 weex 渲染的小程序,或者就是普通的 H5 网页,甚至是一些 native 的场景(需要 loading 的场景),只要是一块能够在客户端中展示的视图,都能够运用快照技术解决其过程中的白屏或 loading 问题,并且都能做到秒出、可交互。因为快照是一个纯 native 的技术,它的实现本来就不依赖于真实页面的渲染方式,它更需要关心的是更合适的快照时机和应用场景从而获取更佳的体验。

总结

我们提出了一种全新的小程序快照技术,实现了小程序首页的秒开和可交互。它能够彻底消除小程序打开过程中的 loading 或白屏现象,让小程序打开达到了 native 的体验,还可以响应用户点击交互。

它是一种纯 native 的技术,不依赖于小程序容器和前端的渲染,只要有视图就能快照,只要有快照数据就能立即展示,甚至可扩展运用于其它非小程序场景。

而其局限性主要是依赖首屏样式和快照时机选择,多变、含用户隐私数据的首屏不适合快照,而且优质快照的生成的时机要求比较苛刻。在快照准确性保障方面,快照的相似度对比方法上也仍然有很大的优化空间,这些都还需要在今后不断打磨。

钉钉小程序快照技术初窥相关推荐

  1. 微信小程序开发者工具初体验及实现技术初探

    微信小程序是当前的热点,市面上已经有很多微信小程序开发相关的文章,今天晚上抽了点时间折腾了微信小程序,并顺便看看了下微信小程序开发者工具的实现,是使用Node.js开发的,UI是基于NW.js框架开发 ...

  2. 钉钉/支付宝小程序自定义组件

    钉钉/支付宝小程序自定义组件 1.新建自定义文件夹 eg:model 2.鼠标选中model 右键>新建小程序组件 输入测试组件:demo 3.新建小程序组件包含四个文件: 1.acss:组件页 ...

  3. 小程序 input自动换行_直播 | 最实用的微信小程序自动化测试技术独家揭秘

    随着微信小程序的功能和生态日益完善,很多企业级小程序项目的页面越来越多,业务逻辑也越来越复杂.如何做好微信小程序的自动化测试成为测试同学面临的一大难题. 如何合理构建多端架构和自动化测试体系? 如何深 ...

  4. 用小程序组装App,小程序容器技术好比基建

    2021年10月20日,在高德纳IT博览会上,Gartner发布企业机构在2022年需要探索的十二大重要战略技术趋势,"组装式应用"位列其中,作为三大主题之一"塑造变化& ...

  5. 微信小程序开发技术预研分析报告

    预研背景 本次预研是对微信小程序使用流程及开发技术的研究. 预研目的和意义 本次预研在于了解小程序具体语法.接口功能.具体实现方式等. 预研目标 通过微信小程序的技术研究可实现自主完成小程序的功能开发 ...

  6. 微信小程序存在的风险_微信小程序开发技术风险存在,如何规避是重点

    微信小程序开发技术风险存在,如何规避是重点 微信小程序自上线以来已经历经三年的时间,不断推陈出新,推展业务,如今已形成了一定规模和影响力,线上购物.在线点餐.预订服务.便捷出行.小游戏等多种多样的小程 ...

  7. Mac应用打开小程序的技术解决方案

    小程序逐渐打通所有应用场景,打破移动端和PC端的边界,解决了频繁在桌面设备和移动设备间跳转带来的「割裂感」,使用户在办公.学习.娱乐时带来极大便利.在未来,小程序将成为万物互联的连接器,打破物理边界. ...

  8. App/H5/小程序测试技术

    本节大纲 ØApp测试概述与流程 ØApp测试策略详解 ØH5测试与小程序测试概述 ØH5测试与小程序测试技术详解 01 App测试概述与流程 定义 1.手机测试 Ø 手机测试是一个很大的题目,涉及到 ...

  9. 将小程序容器技术应用到物联网IoT生态建设中

    智能汽车.智能社区.智能穿戴设备等技术的不断成熟及应用,与其紧密结合的物联网(IoT)正日益成为个人和企业工作生活中的重要组成部分,它为企业和个人带来了操作流程的改进和更好的生活体验,再加上人工智能( ...

最新文章

  1. yolov5 v3.0训练出现KeyError错误
  2. 私有云的优缺点_2019年中国云计算行业竞争格局与发展趋势分析「图」
  3. 网易倩女找不到服务器,新倩女幽魂9月21日一直正在连接服务器_新倩女幽魂9月21日服务器一直连接解决办法_玩游戏网...
  4. ORACLE基础语法学习
  5. startssl申请免费ssl证书
  6. sql缩进提高语句的可读性_为什么要使用列缩进来提高代码的可读性
  7. android倒计时动画特效,Android仿活动时分秒倒计时效果
  8. Word 2007批注及批注者姓名修改技巧
  9. python sorted函数
  10. 项目操作案例丨西门子PLC通过网关连接ACS800变频器
  11. html5 dom video,HTML5 / HTML5 video - 使用 DOM 进行控制 - 汇智网
  12. 第十届网络文化节活动和流程
  13. 2020年11月 工信部考试——Hadoop(数据应用技术)中级认证 1
  14. 在线直播|是事实还是贩卖焦虑?IT行业也偏爱“小鲜肉”
  15. Swig/CPP2Java
  16. java实现doc互转docx
  17. 【51单片机】:智能台灯设计(自动、手动双模式)
  18. 基于java的网上零食销售系统的设计与实现
  19. 【Python 实战】---- 批量修改文件名和将txt转excel
  20. php简易留言板功能,php简单的留言板与回复功能具体实现

热门文章

  1. docker mysql 内存大小_docker容器内存占用过高(例如mysql)
  2. 如何加快疫苗生产?答案在技术领域而非医学领域
  3. iphone 后台循环播放音乐
  4. NodeJS 频繁请求服务器限速工具
  5. UE5打包安卓环境搭建
  6. 利用python处理Excel表格中的销售数据
  7. 五中高考的成绩单2021查询,北京五中高考成绩解读
  8. 使用 OpenCV 识别图片中的猫咪
  9. python里defoults_Python Part.Compound方法代码示例
  10. 自己实现一个Spring 框架