微信小程序技术演进:从内部开放到 JS-SDK 发布

2024-06-22
来源:网络整理

作者:,腾讯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与对比

- 与小程序底层框架对比

多终端小程序原理分析

小程序架构设计(一)

小程序架构设计(下)

腾讯程序员视频号

欢迎点赞最新视频

分享