在轻应用混战的当下小程序已经成为巨头们角逐的焦点阿里自然也不甘落后。据阿里官方的数据截止到今年1月28日为止支付宝小程序应用数已经达到12万总用户数突破5亿日活跃用户数突破2.3亿用户通过支付宝首页下拉入口进入小程序的日人均打开次数为4次支付宝小程序也因此被称为“蚂蚁金服未来三年最重要的战略之一”。
然而支付宝公开的信息更多面向的是普通用户开发者能获知的信息少之又少为此InfoQ采访了支付宝小程序首席架构师白招拒为大家解读支付宝小程序的技术架构和开发特点以下是采访的全部内容。
支付宝小程序从2016年开始立项算起到现在也快3年的时间在这3年的过程中小程序的技术架构也是不断的升级和演进在满足业务发展的同时对于小程序整体的高可用、性能优化、多端输出方面做了大量的工作。今天给大家分享下我们在支付宝小程序技术这块所做的一些工作。
小程序技术架构主要分成四个方面来讲
1.系统架构主要给大家说下小程序的架构以及其中的一些关键技术
2.性能体验讲下我们在性能体验这块做的几个case
3.开发者工具怎么更好的帮助开发者开发和管理小程序和保障线上小程序的质量
4.多端inside将支付宝小程序的技术输出给集团和外部的商户让他们具备运行小程序的能力。
系统架构
支付宝小程序不是从零开始建设的一个产品而是依托于蚂蚁技术部多年来的技术沉淀再结合小程序的业务场景逐步的发展起来的。
以上是支付宝小程序架构的示意图最上面是支付宝钱包提供的主要的七个场景入口开发者可以根据自己的业务场景运营这些场景入口把这些入口的流量充分利用起来。中间框内的是小程序的核心引擎上面是对开发者提供的基础组件和基础API能力开发者根据这些组件和API来开发自己的小程序满足用户的需求。
小程序前端框架这块借鉴了主流前端框架React的设计思路从小程序的应用形态提供了简洁的编程模型定义了一套组件和API接口的规范降低了学习门槛方便开发者快速开发小程序。在小程序框架内部提供了小程序的生命周期管理通过事件的方式把小程序每个阶段都注入到小程序里面开发者可以通过这些事件来处理小程序每个阶段需要完成的业务逻辑。同时框架内部使用了虚拟DOM来处理页面的每次更新提升了页面的渲染性能。
前端框架下面是小程序native引擎包括了小程序容器、渲染引擎和Javascript引擎这块主要是把客户端native的能力和前端框架结合起来给开发者提供系统底层能力的接口。在渲染引擎上面支付宝小程序不仅提供JavascriptWebview的方式还提供JavascriptNative的方式在对性能要求较高的场景可以选择Native的渲染模式给用户更好的体验。
示意图左边和右边分别是面对开发者提供的研发支撑和运维支撑服务可以帮助开发者更有效率的开发小程序在上线后也提供众多的工具帮助开发者管理和运营线上的小程序。
运行时架构
小程序编程模型是分为多个页面每个页面有自己的template、CSS和JS实际在运行的时候业务逻辑的JS代码是运行在独立的Javascript引擎中每个页面的template和CSS是运行在各自独立的webview里面页面之间是通过函数navigateTo进行页面的切换。
每个webview里面的页面和公共的Javascript引擎里面的逻辑的交互方式是通过消息服务页面的一些事件都会通过这个消息通道传给Javascript引擎运行环境这个运行环境会响应这个事件做一些API调用可调到客户端支付宝小程序提供的一些能力处理之后会把这个数据再重新发送给对应的页面渲染容器来处理把数据和模板结合在一起来在产生最终的用户界面。
浏览器内核
小程序在web上的渲染引擎是浏览器内核作为小程序的核心组件经过多方面的考虑我们采用的是UC提供的浏览器内核UC的同学在浏览器内核的性能、稳定性和兼容性上做了大量的工作比系统提供的webview提升了不少。
稳定性crash率只有系统webview的三分之一到五分之一
兼容性不存在各种系统webview上的兼容性问题
性能针对内核启动逻辑v8引擎codecache深度优化使得js代码解析和编译的时间减少40%左右
工具提供了丰富的工具保障UC内核的稳定性和性能
下图是UC内核的稳定性保障体系
同时UC内核针对内存做了大量的优化主要分为几方面
1.图片内存针对低端机做了更严格的图片缓存限制在保持性能体验的情况下进一步限制图片缓存的使用多个webview共用图片缓存池全面支持webp、apng这种更节省内存和size的图片格式。
2.渲染内存Webview在不可见的状态下原生的内存管理没有特殊处理UC内核会将不可见webview的渲染内存释放渲染内存的合理设置与调优避免滚动性能的下降和占用过多内存。
3.JS内存更合理地处理v8内存gc在启动时延时执行full gc避免影响启动的耗时。
4.峰值内存管理系统在内存紧张时会通知内核UC内核能够在系统低内存时释放非关键内存占用的模块避免出现oom也避免过度释放带来的渲染黑块在部分oom的情况规避原生内核主动崩溃的逻辑在内存极低的情况部分功能不可用而不是崩溃。
性能体验
Google 的统计表明页面打开时间超过 3 秒用户会流失 13%超过 6 秒用户会流失 60%。反过来打开时间每减少 1 秒可提升 27% 的转化率给用户带来更好的用户体验一直是支付宝努力在做的事情。
支付宝app不同于社交类的app属于低频类的应用所以在小程序的优化方式上会不同于高频的应用由于高频的应用长期在系统层面是活跃的状态所以高效的优化方式就是预加载在后台把小程序相关的资源尽可能的提前加载好在用户使用小程序时可以快速的启动起来。
而对于低频应用更多的是冷启动所以在这种情况下我们更多的是从技术的角度来优化每一个环节的性能在小程序用户体验上可以达到高频应用下面我会分享几个我们性能优化方面的工作。
render和worker交互优化
为了优化小程序的交互体验目前传统的做法是把render层和woker层在两个不同的线程里面执行可以让页面在渲染的时候不会因为业务逻辑的执行而产生卡顿提升了渲染的速度。
通常的做法是在webview里面运行render的代码然后另起一个线程运行serviceworker当serviceworker需要更新dom的时候把事件和数据通过messagechannel发送给render线程来执行当业务需要传递到render层数据量较大对象较复杂时交互的性能就会比较差因此针对这种情况我们提出一个优化的解决方案。
该方案将原始的JS虚拟机实例(即Isolate)重新设计成了两个部分Global Runtime和Local Runtime。
Global Runtime部分是存放共享的装置和数据全局一个实例。
Local Runtime是存放实例自身相关的模块和私有数据这些不会被共享。
在小程序里面需要做的事情包含两个部分
1.轻量级的js线程替换serviceworker来执行小程序业务逻辑的代码
2.更高效的worker层和render层交互方式。
对于这两个目标我们重新设计了现有的JS虚拟机V8提出了一种优化的隔离模型Optimized isolation model, OIM。OIM的主要思路是共享JS虚拟机实例中与线程执行环境无关的数据和基础设施以及不可变或不易变的JS对象使得在保持JS层逻辑隔离的前提下节省多实例场景下在内存和功耗上的开销。尽管有些实例间共享的数据会带来同步的开销但是在隔离模型下本方案所共享的数据、对象、代码和虚拟机基础设施都是不可变或者不易变的所以很少发生竞争。
在新的隔离模型下webview里面的v8实例就是一个Local Runtimeworker线程里面的v8实例也是一个Local Runtime在worker层和render层交互时setData对象的会直接创建在Shared Heap里面因此render层的Local Runtime可以直接读到该对象并且用于render层的渲染减少了对象的序列化和网络传输极大的提升了启动性能和渲染性能。
首页离线缓存优化
首页的加载和渲染对于冷启动是非常关键的为了减少用户在首页显示前的等待时间我们采用离线缓存的方式来优化加载的流程。对于正常的加载逻辑用户在点击小程序图标后就开始启动的过程下载并解压小程序离线包找到入口的页面index.html作为参数传给浏览器内核开始加载小程序页面。
在浏览器开始加载小程序页面时会先出现三个圆点的Loading页然后在开始加载小程序的前端框架在前端框架加载过程中会启动异步的worker线程加载业务的js逻辑代码前端框架则继续加载小程序的页面并渲染出首页展现给用户。
为了尽快的把首页展现给用户在用户首次展现首页后我们会把首页的UI页面保存下来在用户下次重新打开小程序的时候会首先渲染上次保存下面的首页UI页面把首页展现给用户然后在后台继续加载前端框架和业务的代码加载完成后再和离线缓存的首页UI进行合并给用户展现动态的首页。
由于在渲染完离线缓存的首页UI到真正的业务代码加载完成这个之间的时间大概在1秒左右所以在用户看到首页并做出反应时动态的首页已经合并完成并可以对用户的操作做出响应。
在实现首页离线缓存这个特性中我们面临两个技术上的挑战
1.首页离线缓存页面保存的时机
由于小程序启动是受到生命周期的控制从onLaunch -\u0026gt; onLoad -\u0026gt; onShow -\u0026gt; onReady -\u0026gt; 用户操作 -\u0026gt; 离开首页这个流程在这个过程中的任意一个环节都有可能被客观或者主观的原因打断也就有可能导致保存的离线页面不准确在启动的时候给用户呈现错误的页面。
所以对于首页离线缓存渲染的效果保存页面的时机很重要我们提供让开发者可以配置的时机配置的时机有两个渲染完成和离开首页前。对于渲染完成就是首页渲染完成用户还未执行任何的操作前把页面保存下来作为离线缓存的页面。离开首页前就是指用户在首页执行了一系列的操作后跳转到其他页面前用户看到的页面保存下来作为离线缓存的页面。
针对离开首页前保存页面的问题我们设计了一个事件的队列小程序生命周期中可能对首页改动的事件都会被捕捉同时放入到一个队列里面异步线程会定时的从队列里面拿事件然后延迟执行保存首页的操作由于经常对浏览器内核执行保存操作对性能是有影响的所以会对这些事件进行合并处理最终会以最后一个正确保存的首页为准。
2.离线缓存首页和动态渲染首页替换时的闪屏
对于闪屏问题发生的场景是因为缓存页面和真实渲染的页面是分离的是两个独立的页面缓存页面是静态的页面真实的页面是通过js动态创建的页面所以常规的做法就是当真实页面创建完成后替换缓存的页面这样的情况下就会发生闪屏。
针对这个问题我们是采用虚拟dom来解决在加载缓存页面的时候把缓存页面放入初始的虚拟dom里面真实页面创建后产生的虚拟dom跟缓存页面的虚拟dom进行dom diff把变化的内容通过patch传给浏览器内核渲染对应的页面这样就可以只更新局部有变化的页面内容避免了整个页面的更新也保证内容的准确性和实时性。
通过实测数据显示这个优化可以将小程序的冷启动实现秒开。
虚拟dom优化
小程序的页面渲染采用的也是业界普遍在使用的虚拟dom技术该技术可以保障在更新页面时只更新变动的部分提升了更新的效率。不足的地方就是虚拟dom也是用js来实现在运算时会大量消耗cpu执行的效率不高。
Javascript是一种弱动态类型的语言不同于静态类型的C和Java语言相较而言JS的运行性能会差一些因为类型的不确定性限制了JIT优化编译器生成代码的质量。
针对这种情况我们选择WebAssembly作为虚拟dom的实现方向WebAssembly是一个新的Web标准它定义了网页中的可执行代码的二进制格式和相应的类似汇编语言格式。他的目标是使执行代码几乎与本地机器代码一样快它被用来作为Javascript的补充以加速Web应用程序的性能关键部分所以我们使用WebAssembly技术重新实现了虚拟dom这块的核心代码提升了小程序的页面渲染。
在做这个优化的时候我们面临js代码桥接到WebAssembly的性能较差的挑战因为js引擎和WebAssembly是两个独立的引擎他们之间的交互比js到js的性能要差了不少针对这个问题我们参考了业界的一些实现对V8的代码进行了优化解决js \u0026lt; -\u0026gt; WebAssembly交互性能差的问题。
在做这个优化前我们需要先了解下到底是什么原因导致了js和WebAssembly交互性能差。由于JS和WebAssembly是两种不同类型的语言所以引擎执行过程中遇到语言切换的时候需要做一些“翻译”工作。而这些翻译工作需要考虑各种情况需要跳转到一个专门的trampoline stub处理。
由于在小程序前端框架的实现代码是TypeScript来开发的所以框架在调用虚拟dom的WebAssembly的函数时是可以传入具体的参数类型并且参数的顺序也是固定的但是这些参数类型和参数顺序在到js引擎的时候就丢失了所以需要做一些额外的“翻译”工作降低了交互的性能。
我们的思路就是精简这些翻译的工作在开发层面把框架和WebAssembly的交互代码的参数类型和顺序都固定下来不让其变动。同时我们让js引擎支持了参数类型和参数顺序的传入在编译期把代码的参数类型和参数顺序保存下来运行期把js代码和类型文件一起传给js引擎让js引擎可以直接识别该函数的参数类型这样就可以直接进行参数转化的工作然后调用WebAssembly的方法避免跳转到一个通用的参数转换的trampoline stub上。
通过实测数据表明相比于以前的实现新的实现代码执行效率有50%的提升。
开发者工具
支付宝小程序的目标就是为用户提供高品质的服务这些服务是靠我们的开发者来实现的所以如何帮助开发者提供提供高品质的小程序如何保障线上小程序的质量就是我们一直努力在做的事情。支付宝小程序提供从开发、调试、发布到运维整个链路的工具这些工具也在不断的完善和增强让开发者可以更高效的开发出高品质的小程序。
开发者工具IDE支持mac和windows两个平台的运行通过打通接入研发平台、数据监控、日志收集等系统进一步为桌面客户端的稳定性提供保障。提供多端开发能力通过整合通用能力适配各端差异帮助开发者实现代码的多端调试运行同时可以一键发布到多端。
对于开发新手来说搭建一套完整的后端应用过于复杂涉及到服务器的购买域名购买环境配置等等一系列问题每一个问题都可能阻碍开发者进行下一步操作。为此我们提供了以下两套一站式云服务方案让开发者能够快速高效搭建一套完整的后端服务
云函数将服务器购买配置发布运维等完全解决让开发者只用关心自己的代码逻辑部分的编写并且开发语言是js对于前端开发者非常友好。相比云应用更适合编写轻量级的小程序但是每个云函数只能在绑定的小程序中调用。
云应用将服务器购买配置发布的问题解决相比云函数云应用更加灵活适合编写较复杂的后端应用并且一个云应用可以支撑多个小程序同时调用。我们提供了两种后端语言nodeJs和java用户可以自行选择。
小程序云测试服务可以帮助开发者更全面的检测小程序缺陷评估产品质量提高审核通过率。我们提供了一套完整的小程序云真机自动化检测方案在IDE申请云测试服务执行完成后自动生成测试报告。
云测服务提供“快速检测”、“深度检测” 两种检测模式满足多纬度测试需求并且提供性能检测及优化建议开发者可根据优化建议优化小程序代码提供更好的用户体验。
线上巡检
目前支付宝小程序拥有几十万生态合作伙伴随着小程序生态的不断壮大合作伙伴的数量也在急剧增加如何对生态伙伴提供的服务形成有效的管控如何对小程序的质量进行保障这是我们面临的新挑战。面对这个问题我们在制定相应技术标准和运营规范的同时对小程序从入驻到运营从质量、体验、安全、合规、效能等维度建设了平台化的质量与风险管控能力。
巡检是开发者生态质量与风险保障重要的一环是识别问题的重要手段。\u0008小程序为\u0008开发者提供的服务场景非常丰富而且复杂为解决这一系列问题我们通过自建识别引擎并整合蚂蚁、阿里云等多项基础检测单元的服务能力以“技术一体化平台化”的方式建设主动巡检稽查的能力即巡检平台。
在平台建设过程中我们面临的挑战有
1.开发者提供的服务场景非常丰富且复杂如缴费、医疗、保险、旅行等服务产品呈现多样化
2.小程序提供的是一套前端框架服务内容是由服务端动态呈现随时变化甚至\u0008并且千人千面
3.小程序技术的灵活性因素比如允许内嵌webviewJs动态加载等
4.小程序体量庞大百万应用数千万page并且不断增长。
巡检平台具有以下特点
功能全面可用性、内容合规、信息泄露、图片识别、资源流耗问题的稽查
主动检测主动访问非被动监控先于用户发现尽可能提前将问题暴露
动态渲染支动态加载和页面渲染
高频巡检分钟级高频巡检快速发现问题
多重保障机制双引擎检测、智能复查、智能恢复
多渠道灵活的预警决策多渠道、多阶梯预警工单决策、故障熔断、事后处罚等完备的业务闭环能力
实时数据大屏巡检、故障、预警决策实时监控
多维数据度量多视角、多维护数据大盘
智能高效预警决策环节加入大数据算法运用更智能和高效。
小程序巡检平台从上线以来实现智能化提效94%将小程序审核平均时长从70.59小时下降到4.27小时并实现0积压。根据业务诉求进行不同频率的巡检目前已累计发现和处理了上万个有问题的小程序提升了小程序线上服务的品质。
多端inside
在支付宝小程序发展的过程中集团内的BU也有很强的诉求需要在他们的app端运行小程序扩展他们的商业场景增加用户的活跃度。为了避免重复造轮子大家共享小程序生态也就需要我们从业务和技术上打通小程序的技术栈输出支付宝小程序技术帮助集团内的BU具备小程序的运行能力。
目前支付宝小程序正逐步打通阿里生态开发者可一次开发阿里各大app多端运行通过小程序连接阿里经济体。小程序对外输出的技术主要包含两个部分一个是小程序运行时的SDK这个需要集成到接入的客户端里面另一个是小程序的互通这块需要接入的平台和小程序平台打通大家共享同一个小程序生态。
小程序SDK
小程序输出的SDK包含两个部分基础引擎和能力插件基础引擎是必须的不可替换的它承载了小程序的基础能力包括前端框架和容器的核心能力以及提供渲染的内核。它提供了小程序核心的运行时和基础的核心组件和JSAPI同时提供了能力插件的插件容器插件容器有良好的隔离性不会因为插件的crash导致容器的crash保障了小程序核心运行时的稳定性。
小程序互通
小程序的技术栈除了前端的框架和客户端的运行时还包括开发者的入驻小程序的创建开发和上线以及后续的运维和运营等管理为了给用户和开发者较好的体验小程序的互通是小程序技术输出的必须环节。
平台互通开发者可以在入驻的开放平台管理投放到所有端的小程序包括小程序的开发、调试、测试、发布、运维和管理等一系列的工作。
研发平台互通基于支付宝的开放平台能力统一开发和发布流程通过门户接入互通、开发者体系接入互通、审核能力接入互通、小程序研发链路接入互通、小程序运行链路接入互通实现开发者一次开发、多端投放的能力。
运营管理平台通过统一埋点SDK提供多端小程序自动化埋点能力输出标准化行为、异常与性能数据模型通过数据分析平台提供小程序在各端实时数据分析能力并进一步提供用户特征分析、页面分析、用户留存分析支持小程序研发可视化数据自运营的能力。同时也支持小程序研发自定义数据采集点配置并开放分析管理支持小程序内的用户行为做精细化跟踪、分析满足除页面访问等标准统计以外的个性化分析需求。
工具平台提供给开发者统一的开发者工具帮助开发者更好的开发和测试小程序同时接入的端可以扩展开发者工具的模拟器和特色的jsapi接口方便开发者做端内的特色能力调试。
能力互通支付宝特色能力支付、会员、卡券、信用等能力可以通过扩展jsapi或者插件的方式输出到接入的客户端里面同样的接入的端也可以把自己的特色能力输出到小程序联盟的其他端里面为更多的用户服务。基础能力所有端保持一致客户端特色能力可以通过扩展jsapi的方式集成到小程序api里面也可以通过插件的形式发布到插件市场用户在使用的时候动态下载插件屏蔽端上的差异。
用户互通投放到多端的小程序需要账号绑定用户无需登录给用户提供一致的用户体验。账户通SDK通过提供一套完整的注册、登录、授权、账号绑定管理等基础功能来完成多个APP间账户互通的功能并保障整个过程安全可控。通过账户通可以拓展小程序服务覆盖边界将支付能力、X服务能力覆盖更多的客户让服务通行便利、多端权益打通、多端体验统一。
小程序的inside技术栈不只是针对阿里集团内输出也可以输出到外部的app商户帮助app商户丰富业务场景给用户提供更多有价值的服务。欢迎加入支付宝小程序联盟通过小程序连接到阿里经济体共同壮大小程序生态。
作者简介
白招拒支付宝小程序首席架构师2010年加入蚂蚁金服拥有10多年的互联网研发经验对分布式系统v8引擎客户端前端等领域有深刻的理解。
更多内容请关注前端之巅。
会议推荐
2019年6月GMTC全球大前端技术大会2019即将到来。小程序、Flutter、移动AI、工程化、性能优化…大前端的下一站在哪里点击下图了解更多详情。