找回密码
 会员注册
查看: 32|回复: 0

微信小程序基础架构浅析

[复制链接]

4

主题

0

回帖

13

积分

新手上路

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

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-28 08:06 , Processed in 0.919063 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表