小程序技术演进内部开放微信原生能力使用WeixinJSBridge预览图片

(文末福利:小程序开发工具)

作者:bilgong,腾讯IEG前端开发工程师。

微信小程序,简称小程序,是英文的小程序。是一款无需下载安装即可在微信中使用的应用。用户可以扫描小程序代码或搜索小程序打开。触手可及,用完就可以使用,不用担心是否安装太多应用。

小程序技术演进 内部开放微信原生能力

使用 WeixinJSBridge 预览图片

这种API原本是为腾讯的一些内部业务使用而提供的。很多外部开发者发现后,如葫芦娃般使用,逐渐成为微信网页开发的事实标准。

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的体验和管控的不足呢?

小程序双线程架构

小程序的具体实现采用类网+离线打包的形式。开发类似于web,门槛更低,开发效率更高。离线下载和页面预渲染功能提升用户体验,提升加载速度js做算法在微信小程序,解决JS-SDK加载白屏问题1。小程序提供云端更新离线包的功能,可以动态更新页面,比app的更新发布更加灵活。另外,小程序在离线包的基础上优化了切换动画,减少了切换页面带来的滞后,缓解了切换不流畅的问题2。

小程序网页+离线打包模式

小程序在架构方面最大的特点是采用双线程开发模式,将JS逻辑和UI渲染隔离开来。小程序的渲染层和逻辑层分别由两个线程管理:渲染层的界面使用WebView进行渲染,逻辑层使用JsCore线程运行JS脚本。

逻辑层:创建一个单独的线程来执行JavaScript,在这个环境中所有与小程序业务逻辑相关的代码都被执行;

渲染层:所有与界面渲染相关的任务都在WebView线程中进行,渲染哪些界面由逻辑层代码控制。一个小程序有多个接口,所以渲染层有多个WebView线程;

通信:两个线程之间的通信会通过微信客户端(以下也用Native来指微信客户端)进行中继,逻辑层发出的网络请求也会通过Native进行转发。小程序的通信模型如下图所示。

小程序双线程架构

JS逻辑层运行在JSCore中,没有完整的浏览器对象,因此缺少相关的DOM API和BOM API,无法操作页面元素,可以达到管控的目的,但也限制了开发者的权限:

不允许开发者跳转到其他在线页面 不允许开发者直接访问 DOM 不允许开发者在窗口上随意使用一些未知且有潜在危险的 API

这种逻辑层和UI层的分离,再加上小程序的审核和报告机制,使得微信加强了对小程序的控制,解决了问题3。但这也使得开发者无法灵活地渲染页面。

小程序页面渲染

如上所述,逻辑层无法操作 DOM 的变化,那么小程序是如何渲染页面的呢?小程序基于数据驱动的架构模式和 Virtual Dom 的概念(由 React 引入,一种真实 DOM 的 JS 描述方法)。业务方只需要改变数据就可以引起接口的变化。渲染层为 WXML 提供数据绑定语法,逻辑层提供 setData 等 API。当开发者需要更改接口时,只需在逻辑层执行 setData 即可将更改后的数据通过 Native 层传递给渲染层。,小程序会执行Dom Diff(一种DOM结构比较和最小化变化的算法)等过程,最后在Dom树上更新正确的结果。

图片[1]-小程序技术演进内部开放微信原生能力使用WeixinJSBridge预览图片-老王博客

小程序虚拟 DOM 渲染

完整的通信流程大致如下:

逻辑层调用宿主环境的 setData 方法。逻辑层将要传输的数据转换成字符串,拼接成具体的JS脚本,最后将数据传输到渲染层。渲染层收到后,WebView JS线程会编译脚本,拿到要更新的数据后进入渲染队列,等待WebView线程空闲时渲染页面。当WebView线程开始进行渲染时,待更新的数据会被合并到视图层保留的原始数据数据中,新的数据会应用到WXML片段中,得到一个新的虚拟节点树。比较新的虚拟节点树和当前节点树的差异后,将差异部分更新到 UI 视图。

小程序方案与 React Native 对比

那么小程序与现有的混合开发技术类型有哪些异同呢?尤其是和 React Native 的区别,小程序技术架构为什么不使用 React Native?

混合开发技术的类型

现有的混合开发类型,根据UI渲染的分类,主要分为两类:

基于 WebView UI 的基本解决方案。市面上的主流,比如微信JS-SDK,都是通过JSBridge完成H5和Native的双向通信,从而赋予H5一定的原生能力。基于 Native UI 的解决方案,如 React-Native、Weex、Flutter 等。在赋予 H5 原生 API 能力的基础上,进一步通过 JSBridge 将 JS 解析为虚拟 DOM 并传输到 Native,并使用原生渲染。

小程序也属于类型 1,这次我们主要使用类型 2 中的 React Native 作为对比分析。

React Native 技术架构框架

React Native 框架具有三个主要层:

JS层:该层为开发者提供各种组件和一些工具库(事件分发等)。C++层:主要处理java/OC与JS(JSBridge)的通信以及JavaScript(JS脚本引擎)的执行。Native层(Object C/Java层):主要包括UI渲染器、网络通信等工具库。根据不同的操作系统有不同的实现。界面渲染

React Native 基于 React 框架(Virtual Dom)进行 UI 渲染。具体流程大致如下:

首先,JS层通过JSX编写的Virtual Dom构建ComponentNative层,将其转换为真实的DOM,插入到原生App的页面中。当有变化时,diff算法生成差异对象,最后原生层将差异对象应用到原生应用的页面元素上。沟通

React Native 基于 JSCore 实现了 js 与 java/oc 的交互。具体流程大致如下:

将JSX代码解析成javascript代码,读取JS文件,使用JS脚本引擎执行并返回一个数组。该数组将描述OC/Java对象,描述对象属性和要执行的方法,以便设置对象。,并调用该方法。

反应式原生架构

React Native 原生渲染的优缺点,性能更好,用户体验更好;更好的 React 生态,对前端开发友好;混合技术的跨平台开发,成本和难度低于原生;热更新,易于迭代。缺点支持的样式是 CSS 的子集,无法满足 Web 开发者日益增长的需求;现有能力下还存在一些不稳定的问题,比如性能、bug等;所有的渲染工作都交给客户端进行原生渲染,会有更原生的体验,但实际上一些简单的界面元素完全可以使用Web技术进行渲染;React Native 之前暴露了一个开源协议问题(Facebook BSD+Patents,大致内容是基于Facebook BSD+Patents协议的,如果以后因为专利问题与Facebook发生纠纷,那么Facebook将有权阻止你使用开源项目),这也是一个隐患将来。小程序不选择 React Native 的原因

据小程序开发者介绍,原因如下:

React Native 只支持 CSS 的一个子集。作为一个开放的生态系统,开发人员需要了解哪些 CSS 属性可以使用,哪些不能使用。这样的开发体验很差;(对应上面的缺点1)React Native本身就存在一些问题,这些都依赖RN的修复,同时也变得过于依赖客户端发布版本来解决开发者的bug侧面,而且修复周期太长。(对应上面的缺点2)React Native也有很久了,搞出一个开源协议问题也是一个隐患。(对应于以上缺点4)小程序和React Native与混合技术的优点一样:接近原生体验js做算法在微信小程序,跨平台开发使用Web相关的技术框架来编写业务代码,React Native就是React框架,applet就是小程序开发框架。各自实现了跨语言通信方案,完成Native(Java/Objective-c/…)端和JavaScript(渲染层和小程序中的小程序)。逻辑层的通信小程序)与React Native不同

小程序使用浏览器内核WebView来渲染界面(少量原生组件由客户端渲染)。界面以成熟的Web技术渲染为主,辅以大量的界面,提供丰富的客户端原生能力,而React Native则是客户端的Native渲染。理论上,React Native 比 WebView 有更好的性能,但小程序的类 web 开发相对容易上手,这就像一把开发效率和性能的双刃剑。

小程序开发笔记

基于以上架构分析,我们在开发过程中需要注意以下几点:

避免使用操纵 DOM 的 npm 包。由于逻辑层和渲染层的隔离,逻辑层无法操作DOM/BOM API,所以在与DOM/BOM API相关的npm包和库中不可用。避免频繁调用 setData。由于setData中的数据不仅需要通过Native层传递给渲染层,还要通过DOM diff算法渲染到最终页面,所以需要尽量减少setData的使用,避免出现性能问题。避免 setData 传递大量新数据。数据传输会经过跨线程传输和脚本编译的过程。当数据量过大时,会增加脚本编译的执行时间,占用WebView JS线程,从而影响最终的渲染性能。

参考文档

小程序介绍 | 微信开放文档小程序介绍 | 微信开放文档

React-Native和小程序底层框架对比 – 云+社区 – 腾讯云

微信小程序原理解析及多端小程序架构原理(应该是全网最全的) | 航笔ejue的个人博客

小程序架构设计(一) | 微信开放社区

小程序架构设计(二) | 微信开放社区

福利时间

画5位小伙伴送《小程序开发原理与实战》,腾讯一线高手带你学习小程序开发,干货满满!点击这里:福利参与!

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论