作者:,腾讯IEG前端开发工程师。
微信小程序,简称小程序,是微信中无需下载安装即可使用的应用程序,用户通过扫描小程序码或搜索小程序即可打开,触手可及,用完即走,不用担心安装过多应用。
小程序技术演进:对内开放微信原生能力
使用预览图像
这类API最初是提供给腾讯内部的一些业务使用的,后来被很多外部的开发者发现后,纷纷效仿,并逐渐成为了微信Web开发的事实标准。
JS-SDK 发布
2015年初,微信发布了一整套Web开发工具包JS-SDK,开放了拍照、录音、语音识别、二维码、地图、支付、分享、优惠券等几十个API,让所有开发者都能使用微信原生的能力。
使用JS-SDK调用图片预览组件
JS-SDK 解决了微信在移动网页能力不足的问题,通过开放微信接口,让 Web 开发者拥有更多的能力,但尽管增加了能力,JS-SDK 模式并没有解决移动网页使用体验不佳的问题。
JS-SDK 的缺点
用户在访问网页时,在浏览器开始显示之前会有一个白屏的过程。在移动端,由于设备性能和网速的限制,白屏会更加明显。除了白屏,影响网页体验的问题就是操作缺乏反馈,主要表现在两个方面:页面切换的突兀感和点击的迟滞感。
加载时白屏,切换不流畅
另外,有些开发者会利用JS-SDK做一些事情,比如假红包,假官方活动等。并且利用JS-SDK的分享能力,变相分享到各类群或者好友。因为JS-SDK是基于域名来授予API权限的,所以运营商封掉一个域名之后,他们马上就用其他域名继续干坏事。要知道注册一个新域名的成本是很低的。
那么小程序是如何设计来改善JS-SDK的体验和管控不足的呢?
小程序双线程架构
具体实现上,小程序采用类网页+离线包的形式,开发类似网页,门槛更低,开发效率更高;离线下载、页面预渲染功能提升用户体验,提升加载速度,解决加载JS-SDK白屏问题1。小程序提供云端更新离线包功能,可动态更新页面,比APP更新发布更灵活。此外,小程序在离线包基础上优化切换动画,减少切换页面带来的卡顿,缓解切换不流畅问题2。
小程序web+线下套餐模式
该小程序在架构上最大的特点是采用双线程开发模式,将 JS 逻辑与 UI 渲染隔离开来。小程序的渲染层与逻辑层分别由两个线程管理:渲染层界面用来渲染,逻辑层用线程运行 JS 脚本。
逻辑层:创建一个单独的线程来执行。在这个环境中,执行的代码与小程序的业务逻辑相关。
渲染层:所有与界面渲染相关的任务都在线程中执行,由逻辑层代码控制渲染哪些界面。一个小程序有多个界面,因此渲染层就有多个线程;
通信:这两个线程之间的通信会通过微信客户端(以下简称微信客户端)进行中转,逻辑层发送的网络请求也会被转发。小程序的通信模型如下图所示。
小程序双线程架构
JS逻辑层运行在浏览器端,没有完整的浏览器对象,因此缺少相关的DOM API和BOM API,无法操作页面元素,虽然能达到控制的目的,但也限制了开发者的权限:
开发人员不得将页面重定向到其他在线网站
不允许开发人员直接访问 DOM
不允许开发者随意使用一些未知的、有潜在危险的API
这种逻辑层和UI层的隔离,加上小程序的审核和举报机制,使得微信加强了对小程序的管控,解决了问题3。然而,这也使得开发者无法灵活地渲染页面。
小程序页面效果图
上面提到了逻辑层是无法操作 DOM 变化的,那么小程序是如何渲染页面的呢?小程序基于数据驱动的架构模型,有 Dom(引言,真实 DOM 的 JS 描述方式)的概念。业务方只需要改变数据就能够引起界面的改变。渲染层提供了 WXML 和数据绑定语法,逻辑层提供了 等 API。当开发者需要改变界面时,只需要将改变的数据通过逻辑层传递给渲染层,小程序会进行 Dom Diff(一种比较 DOM 结构,最小化变化的算法)等处理,最终将正确的结果更新到 Dom 树上。
小程序 DOM 渲染
完整的通信过程如下:
逻辑层调用宿主环境的方法。
逻辑层将需要传输的数据转换成字符串,拼接成具体的JS脚本,最终将数据传送给渲染层。
渲染层收到之后,JS线程会编译脚本,获取需要更新的数据后进入渲染队列,等待线程空闲之后再渲染页面。
当线程开始执行渲染时,需要更新的数据会和视图层保留的原有数据进行合并,并将新的数据应用到 WXML 片段中,得到新的虚拟节点树。将新的虚拟节点树和当前节点树进行对比后,将差异部分更新到 UI 视图中。同时,新的节点树替代旧的节点树,以便下次重新渲染。
小程序解决方案及比较
那么小程序和现有的混合开发技术类型有哪些相同和不同之处呢?尤其是为什么不采用小程序技术架构呢?
混合开发技术类型
现有的混合开发类型按照UI渲染的分类主要分为两类:
基于UI的基础方案,目前市面上主流的如微信JS-SDK等,完成了H5与UI的双向通信,从而赋予了H5一定的原生能力。
基于UI的解决方案,如:-、Weex等,在赋予H5原生API能力基础上,进一步将JS解析为虚拟DOM并传递,使用原生渲染。
小程序也属于第1类,这次我们主要用第2类来进行比较分析。
技术架构框架
该框架有三个主要层:
JS层:该层提供各种组件供开发者使用,以及一些工具库(事件分发等)。
C++层:主要处理Java/OC与JS()的通信以及执行(JS脚本引擎)。
(C/Java层):主要包括UI渲染器、网络通信等工具库。不同的操作系统有不同的实现。
UI 渲染
基于框架(Dom)进行UI渲染,具体流程如下:
首先使用 JSX 编写的 Dom 构建 JS 层。
该层将其转换为真实的DOM并插入到原生App页面中。
当有变化时,通过diff算法生成差异对象
最后该层将差异对象应用到原生应用的页面元素上。
通讯
基于js与java/oc交互的实现,具体流程如下:
将 JSX 代码解析为代码
读取JS文件并使用JS脚本引擎执行
返回一个描述OC/Java对象、对象属性以及需要执行的方法的数组,以便对象可以设置属性、调用方法。
建筑学
的优点和缺点
原生渲染,性能更佳,用户体验更好;
生态良好,对前端开发友好;
技术跨平台开发,成本和难度较原生平台更低;
可以进行热更新,方便迭代。
缺点
支持的样式是CSS的子集,不能满足Web开发人员日益增长的需求;
现有能力下还存在一些不稳定的问题,比如性能、bug等;
将所有渲染工作留给原生客户端渲染将提供更接近原生的体验,但实际上一些简单的界面元素可以使用Web技术来渲染。
之前就曝光过一个开源协议问题(BSD+,大致意思是基于BSD+协议使用开源项目的开发者,将来如果因为专利问题产生纠纷,他们有权阻止你使用该开源项目),这也给未来埋下了隐患。
不选择小程序的原因
小程序开发者给出的理由如下:
仅支持 CSS 的子集,作为开放的生态,开发者需要知道哪些 CSS 属性可以使用,哪些不能使用,导致开发体验不佳。(对应上文缺点 1)
本身就存在一些问题,需要依赖 RN 的修复。同时这也变得过于依赖客户端发布版本来解决开发者端的 Bug,修复周期太长。(对应上面的缺点 2)
前段时间开源协议出了问题,同样存在隐患。(对应上面的缺点4)
小程序与相似之处
两者都具有技术优势:近乎原生的体验、跨平台开发
使用Web相关技术框架编写业务代码,作为框架,使用小程序作为小程序开发框架。
各自实现了跨语言通信方案,完成(Java/-c/…)端与(小程序中的渲染层和逻辑层)的通信
小程序及其区别
小程序采用浏览器内核渲染界面(少量原生组件由客户端渲染),界面以成熟的Web技术渲染为主,辅以大量接口提供丰富的客户端原生能力。理论上性能更优,但Web化的小程序开发对于开发者来说上手相对简单,这对于开发效率和性能来说犹如一把双刃剑。
小程序开发笔记
基于以上架构分析,我们在开发中需要注意以下几点:
避免使用操作 DOM 的 npm 包。由于逻辑层和渲染层是隔离的,逻辑层无法操作 DOM/BOM API,所以不能使用与 DOM/BOM API 相关的 npm 包和库。
避免频繁调用。由于函数内的数据不仅需要层层传递到渲染层,还需要经过 DOM diff 算法渲染到最终的页面中,因此需要尽量少用,避免出现性能问题。
避免传递大量新数据。数据传输会经过跨线程传输、脚本编译的过程,当数据量过大时,会增加脚本编译的执行时间,并占用 JS 线程,从而影响最终的渲染性能。
参考文档
小程序官方文档
小程序原理及RN与对比
- 与小程序底层框架对比
多终端小程序原理分析
小程序架构设计(一)
小程序架构设计(下)
腾讯程序员视频号
欢迎点赞最新视频