[TOC]
前言
- 我们前期在探索iOS动画及渲染相关原理 的时候,先后了解了:
- 我们作为一个程序员,在提升技术能力水平的时候,有几种学习方法,比如,
链式学习法、环式学习法、比较学习法等。
- 很明显,我们在探索iOS动画及渲染相关原理 的时候用的就是
链式学习法。- 紧接着,为了拓宽自己的知识面,对相同课题的做一个相对系统的认识,我们将采用
环式学习法,去探索相关的几个课题:- 以上皆是以
iOS Native开发的角度去关注的,换一个维度去考虑的话,我们当然少不了应当去关注WebApp、跨平台开发的技术方案,你猜的没错,我在这里用的是比较学习法,相关的课题:- 当然了,在我们今天这个时代的技术生态,阿里、腾讯、百度等大厂还推出了小程序,所以我们也要关注一下
- 小程序框架的渲染原理 本文就是为了讲述
小程序框架的渲染原理的页面渲染原理而展开的 !!!小程序:
- 自Tencent的微信事业部的leader
张小龙发布微信小程序以来,广大互联网用户都体验到了小程序带来的短、平、快的小程序服务。自此,如此随装随走、用完则放的轻应用模式在国内互联网掀起了一股旋风。- 紧随着
微信的步伐,后来各大网络巨头如阿里、百度、京东、字节跳动等都相继退出了自家的小程序平台。- 移动互联网生态由此也进一步演进为:超级 APP + 小程序成为「轻应用时代」下的新生态。那么小程序到底是什么呢?它的渲染逻辑又是如何的呢?接下来就让我们一步一步去探索吧!
何为小程序?
让我们引入字节跳动平台对
字节小程序的官方文档的一段介绍:
- 小程序是一种新形式的应用程序。
小程序开发的模式与 Web 开发类似:使用 JavaScript 进行开发,使用 CSS 控制样式,最终使用 HTML 进行渲染。- 但是,我们开发的小程序的 JS 代码,其实是运行在一个被称为
“逻辑层”的独立运行环境中(大多数情况下),并且每个小程序有且仅有一个“逻辑层”。- 在 Web 开发中,每个页面中 JS 线程与渲染线程是互斥的;
- 而在小程序中,JS 的运行进程与渲染进程(视图层)是独立的,视图的渲染更新,并不会阻塞 JS 的执行,同时 JS 的逻辑执行,也不会阻塞视图的渲染更新。
- 这里产生了我们需要注意的第一个问题:
JS 驱动视图的更新是异步的,并且 js 无法直接访问视图的 DOM在 Web 开发中,我们的
运行环境是浏览器,无论是 JS,还是 HTML/CSS,都是运行在浏览器中的。所以,对于我们的 Web 页面,可变的环境是浏览器,我们可能需要处理 safari/chrome/firefox 等 Web 浏览器带来的功能与渲染差异。而当我们开发小程序的时候,也需要处理运行环境的差异,不过小程序的环境差异指的是不同小程序宿主平台工程的差异接下来让我们看看阿里的
支付宝小程序的一段简介:支付宝小程序是一种全新的开放模式,让合作伙伴有机会分享支付宝及阿里集团多端流量和商业能力,为用户提供更好的体验,
助力商家经营升级。何为小程序的
宿主(平台工程)?
- 首先,我们所知道的具有小程序能力的互联网巨头有不少,比如
阿里、百度、京东、字节跳动等- 其次,这些公司的互联网产品很多。我们
小程序开发者朋友在开发完其中一个平台的小程序后,需要投放到该平台上去,而该平台会将这个小程序投放到他们公司的互联网产品中支持小程序服务的宿主工程中去。- 这个宿主工程其实就是他们不同业务方向的主打互联网产品,比如:
阿里的支付宝、腾讯的微信、字节的抖音、今日头条等总结:
小程序就是一个轻便级的应用,是一个借助互联网巨头的用户流量进行拓展业务推广的好点子。
它是当下扩展互联网生态的一个新形势。各大互联网巨头根据自己的业务定位相继退出自家小程序,帮助合作伙伴更好运营其产品,实现产业生态共生。
小程序的开发方式与Web开发相近,但又比Web更简介,不同平台的小程序依赖不同平台的宿主。
各大小程序平台都为开发者提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在开发小程序的过程中有较好的体验、服务。我们今天不针对小程序如何开发等小程序关注的其他问题。
我们今天主要以微信小程序、支付宝小程序为样例,关注小程序框架的渲染原理展开讨论:
概述
小程序方式构建应用是大趋势,被越来越多的企业用户看到其中的优势,企业用户可以借助小程序平台的用户流量,将自己的平台加以推广。搭建小程序,帮助企业用户构建一个具备小程序能力的“移动门户”的一种新思路。
目前可喜的是有朋友已经实践了构建一个跨多端平台的小程序开发平台,并且收获了可喜的效果。我们就可以不用不同的小程序平台开发多套代码了!!由于小程序的盛行,互联网生态由此进一步演进成:超级 APP + 小程序成为「轻应用时代」下的新生态。
接下来,就让我们一起去看看,小程序的渲染原理吧!
本文内容结构
一、微信小程序
二、支付宝小程序
三、总结
四、文章推荐
相关约阅读(共计14篇文章)
一、微信小程序
在介绍小程序框架的渲染原理之前,首先还是得回归到对小程序进行相关的简介来,说到介绍小程序,我们首先来关注其项目结构
1.1 项目结构
- 页面结构
- 页面结构文件为index.wxml,通过微信自定义的标签来写。
- 页面逻辑
- 页面逻辑通过JavaScript来书写。
- 页面样式表
- 类似CSS文件,来定义页面内元素的样式。
- 页面配置
- 页面内的权限等配置信息。
在前面的篇幅中,我们有提及到,无论是哪个平台的小程序,都是依赖小程序的宿主(工程)的。那么,小程序究竟依赖了宿主工程的什么呢? 让我们接下来一步一步去了解!!!
1.2 小程序的渲染
渲染界面的技术
在介绍小程序的渲染之前,我们不妨先了解一下两种渲染:
- 纯 Native 技术渲染
- 缺点:无法动态打包,动态下发。
- 用纯 WebApp 技术来渲染(页面渲染和JS逻辑层共用一个线程,且只有一个WebView)
- 缺点:如果我们用纯 Web 技术来渲染小程序,在一些有复杂交互的页面上可能会面临一些性能问题
- 我们在另一篇文章中曾讨论过WebApp或类RN技术渲染原理,其中有提及WebKit的渲染
- 在 Web 技术中,UI渲染跟 JavaScript 的脚本执行都在一个单线程中执行,这就容易导致一些逻辑任务抢占UI渲染的资源。、
小程序技术是介于纯Native和纯Web之间的Hybrid技术
- 介于客户端原生技术与 Web 技术之间的,互相结合各自特点的技术来渲染(
Web页面渲染与JS逻辑层是分别两个线程来执行,两者之间不会产生阻塞) - 微信 JSSDK 这样的 Hybrid 技术,即
①界面主要由成熟的 Web 技术渲染,Web资源能热更新,客户端原生辅之以大量的接口②为其提供丰富的宿主工程Native的能力。 - 同时,微信小程序为Web提供Web页面栈管理:
每个小程序页面都是用不同的WebView去渲染,这样可以提供更好的交互体验,更贴近原生体验,也避免了单个WebView的任务过于繁重
小程序的双线程模型
小程序的渲染层和逻辑层分别由两个线程管理:
渲染层的界面使用 WebView 进行渲染;逻辑层采用 JSCore 运行 JavaScript 代码。- 一个小程序存在多个界面,所以渲染层存在多个 WebView(每一个WebView都单独走WebKit渲染)。这两个线程间的通信经由小程序 Native 侧中转,逻辑层 发送网络请求也经由 Native 侧转发,小程序的通信模型下图所示。
视图层主要负责页面的渲染逻辑层负责js的执行
视图层与逻辑层之间通过event和data来通信。
- 通信是有微信客户端(Native)做的一层中转;
- 并且,宿主工程-
微信还给小程序提供了JSAPI(JavaScriptInterface),透过jsBridge来调用原生的功能模块,比如:相机、扫码、HUD、网络通讯、数据存储、蓝牙等功能。
- 工作流程简述:小程序H5模块的JS→JSCore→JSBridge(Native中注册JSCore回调,JSBridge负责将JS的调用信号解释出来,进而转发到具体的Native实现类中去)→Native的提供的JSAPI(访问具体的Native功能块)
- 这个
视图层,就是最后我们打包出来的代码,包含了html页面和css样式,在这里面运行,视图层目前使用 WebView 作为渲染载体- 而逻辑层是由独立的 JsCore 作为js的运行环境,所以它和浏览器不一样,只有一些js对应的方法,不能直接操作dom和获取dom,中间都需要通信这一层中转,在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。
- 当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。 即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。
- 由于这之间他们是彼此独立的,是基于消息驱动来渲染的,所以不会阻塞页面;,我的渲染不会影响你的js逻辑,js的执行也不会柱塞渲染的过程;
比如我们在发送一些请求的时候,这种一般是经由Native转发:
1.3 小程序的双线层模型设计思路
为了管控和安全,微信小程序阻止开发者使用一些浏览器提供的,诸如跳转页面、操作 DOM、动态执行脚本的开放性接口。
将逻辑层与视图层进行分离,视图层和逻辑层之间只有数据的通信,可以防止开发者随意操作界面,更好的保证了用户数据安全。
微信小程序视图层是 WebView,逻辑层是 JS 引擎。三端的脚本执行环境以及用于渲染非原生组件的环境是各不相同的:
- 在 iOS、iPadOS 和 Mac OS 上,小程序逻辑层的 javascript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS 14、iPad OS 14、Mac OS 11.4 等;
- 在 Android 上,小程序逻辑层的 javascript 代码运行在 V8 中,视图层是由基于 Mobile Chrome 内核的自研 XWeb 引擎来渲染的;
- 在 Windows 上,小程序逻辑层 javascript 和视图层 javascript 都是用 Chrome 内核;
- 在 开发工具上,小程序逻辑层的 javascript 代码是运行在 NW.js 中,视图层是由 Chromium Webview 来渲染的。
- 移动大前端开发主需要关注三块:
单 WebView 实例与小程序双线程多实例代码执行的差异性
- 单 WebView 模式下,Page 视图与 App 逻辑共享同一个 JSContext,这样所有的页面可以共享全局的数据和方法,能够实现全局的状态管理。
- 多 WebView 模式下,每一个 WebView 都有一个独立的 JSContext,虽然可以通过窗口通信实现数据传递,但是无法共享数据和方法,对于全局的状态管理也相对比较复杂。
- 抽离一个通用的 WebView 或者 JS Engine 作为应用的 JSContext 就可以解决这些问题,但是同时引入了其他问题:视图和逻辑如何通信,在
小程序里面数据更新后视图是异步更新的。- 程序双线程交互的生命周期图示:
1.4 微信小程序的页面渲染
从前面的篇幅我们可以知道,微信小程序是的每一个页面都是有独立的WebView控件来展示的,整个小程序的页面统一由微信的页面栈管理。
而单独WebView页面的渲染,走WebKit的渲染机制的,总体上和原生控件渲染的流程没有太大差异。我在iOS的各个渲染框架以及iOS图层渲染原理、Web和类RN大前端的渲染原理两篇文章中做了详细的介绍,可以进去两个了解更详细的过程。 它与WebApp不同的地方就是:
- ①-WebApp采用单页面实例,其采用多WebView实例,因此其更轻便,渲染性能更佳;
- ②-WebAppJS逻辑层和视图层混合在一起,比较重,且相对而言可维护性比较低。其视图层和逻辑层分别独立,代码更具备可维护性,且不会和JS共用一个Context,不会存在页面渲染逻辑和JS逻辑相互阻塞的情况。
二、支付宝小程序
支付宝小程序的实现和微信小程序的实现方式大致相同,这里主要针对两者的差异性的地方展开讨论。
在介绍支付宝小程序框架的渲染原理之前,同样的我们首先回归到对小程序进行相关的简介来,说到介绍小程序,我们首先来关注其项目结构:
2.1 项目结构
2.2 支付宝小程序的渲染
支付宝小程序的技术和微信小程序一样,是介于纯Native和纯Web之间的Hybrid技术,同样具备双线程模型
支付宝的小程序的双线程模型
小程序的渲染层和逻辑层分别由两个线程管理:
渲染层的界面使用 WebView 进行渲染;逻辑层采用 JSCore 运行 JavaScript 代码。视图层主要负责页面的渲染逻辑层负责js的执行
视图层与逻辑层之间通过event和data来通信。
- Native做一层中转;
- 并且,宿主工程-
支付宝还给小程序提供了JSAPI(JavaScriptInterface),透过jsBridge来调用原生的功能模块,比如:相机、扫码、HUD、网络通讯、数据存储、蓝牙等功能。
- 工作流程简述:小程序H5模块的JS→JSCore→JSBridge(Native中注册JSCore回调,JSBridge负责将JS的调用信号解释出来,进而转发到具体的Native实现类中去)→Native的提供的JSAPI(访问具体的Native功能块)
- 这个
视图层,就是最后我们打包出来的代码,包含了html页面和css样式,在这里面运行,视图层目前使用 WebView 作为渲染载体
支付宝小程序业务架构图:
更优异的渲染引擎
在渲染引擎上面,支付宝小程序不仅提供 JavaScript+Webview 的方式,还提供 JavaScript+Native 的方式,在对性能要求较高的场景,可以选择 Native 的渲染模式,给用户更好的体验
采用UC浏览器内核
在阿里的mPaaS开发套件中,关于H5容器的渲染,在安卓系统中,开发者还可以选择采用UC浏览器内核而不用 谷歌的v8。而在支付宝这个宿主工程里,支付宝的Developer们采用的就是采用UC浏览器内核.以下是采用该内核带来的优势:
-
图片内存:针对低端机,做了更严格的图片缓存限制,在保持性能体验的情况下,进一步限制图片缓存的使用
- 多个 webview 共用图片缓存池;
- 全面支持 webp、apng 这种更节省内存和 size 的图片格式。
-
渲染内存:Webview 在不可见的状态下,原生的内存管理没有特殊处理,UC 内核会将不可见 webview 的渲染内存释放;
- 渲染内存的合理设置与调优,避免滚动性能的下降和占用过多内存。
-
JS 内存:更合理地处理 v8 内存 gc,在启动时延时执行 full gc,避免影响启动的耗时。
-
峰值内存管理:系统在内存紧张时,会通知内核,UC 内核能够在系统低内存时释放非关键内存占用的模块,避免出现 oom,也避免过度释放带来的渲染黑块;
- 在部分 oom 的情况,规避原生内核主动崩溃的逻辑,在内存极低的情况,部分功能不可用,而不是崩溃
2.3 支付宝小程序虚拟机隔离
通常的做法是在 WebView 里面运行 render 的代码,然后另起一个线程运行 serviceworker:
- 当 serviceworker 需要更新 dom 的时候把事件和数据通过 messagechannel 发送给 render 线程来执行;
- 当业务需要传递到 render 层数据量较大,对象较复杂时,交互的性能就会比较差,因此针对这种情况我们提出一个优化的解决方案。
该方案将原始的 JS 虚拟机实例 (即 Isolate) 重新设计成了两个部分:Global Runtime 和 Local Runtime。
- Global Runtime 部分是存放共享的装置和数据,全局一个实例。
- Local Runtime 是存放实例自身相关的模块和私有数据,这些不会被共享。
在新的隔离模型下,webview 里面的 v8 实例就是一个 Local Runtime,worker 线程里面的 v8 实例也是一个 Local Runtime,在 worker 层和 render 层交互时,setData 对象的会直接创建在 Shared Heap 里面,因此 render 层的 Local Runtime 可以直接读到该对象,并且用于 render 层的渲染,减少了对象的序列化和网络传输,极大的提升了启动性能和渲染性能。
2.4 支付宝小程序首屏启动优化
由于小程序启动是受到生命周期的控制,从 onLaunch -> onLoad -> onShow -> onReady -> 用户操作 -> 离开首页这个流程。
在这个过程中的任意一个环节都有可能被客观或者主观的原因打断,也就有可能导致保存的离线页面不准确,在启动的时候给用户呈现错误的页面。
所以对于首页离线缓存渲染的效果,保存页面的时机很重要,支付宝小程序提供让开发者可以配置的时机,配置的时机有两个:渲染完成和离开首页前。\
- 对于
渲染完成就是首页渲染完成,用户还未执行任何的操作前把页面保存下来作为离线缓存的页面。 离开首页前就是指用户在首页执行了一系列的操作后,跳转到其他页面前用户看到的页面保存下来作为离线缓存的页面。
对于闪屏问题发生的场景是因为缓存页面和真实渲染的页面是分离的,是两个独立的页面,缓存页面是静态的页面,真实的页面是通过 js 动态创建的页面,所以常规的做法就是当真实页面创建完成后替换缓存的页面,这样的情况下就会发生闪屏。
针对这个问题,支付宝团队是采用虚拟 dom 来解决,在加载缓存页面的时候把缓存页面放入初始的虚拟 dom 里面,真实页面创建后产生的虚拟 dom 跟缓存页面的虚拟 dom 进行 dom diff,把变化的内容通过 patch 传给浏览器内核,渲染对应的页面,这样就可以只更新局部有变化的页面内容,避免了整个页面的更新,也保证内容的准确性和实时性。
三、总结
通过前面的介绍,我们基本知道了:
- 小程序技术都是介于
纯Web和纯Native之间的Hybrid技术; - 小程序的
视图层和逻辑层分离,视图层中的每一个小程序页面都有单独的WebView实例,页面管理通过页面栈管理器管理 - Native为小程序通过JSAPI为小程序提供能力。宿主工程在框架层,还提供了JSBridge工具用于Native和小程序H5的通讯交互。
- 相较而言,支付宝小程序比微信小程序做了一些优化工作:
- 提供了更优异的渲染机制;
- 采用了UC的浏览器内核
- 做了首屏启动优化
- 对小程序程序坞进行了虚拟机隔离「两套Runtime」
本篇文章,没有解决的问题如下:
- 1.讨论如何进行小程序的敏捷开发;
- 2.对小程序框架的解读;
- 3.对小程序源码的解读;
- 4.小程序实战项目经验分享
- ......
参考
四、文章推荐
- 01-最实用的微信小程序大全,持续更新中...
- 02-强烈推介的几个微信小程序开发小技巧,简单又实用
- 03-使用uni-app开发小程序,比直接原生开发小程序好在哪里?
- 04-小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?
- 05-小程序的全栈开发新时代
相关阅读(共计14篇文章)
iOS相关专题
- 01-iOS底层原理|iOS的各个渲染框架以及iOS图层渲染原理
- 02-iOS底层原理|iOS动画渲染原理
- 03-iOS底层原理|iOS OffScreen Rendering 离屏渲染原理
- 04-iOS底层原理|因CPU、GPU资源消耗导致卡顿的原因和解决方案