浅析小程序运行机制

写作背景

接触小程序有一段时间了,总得来说小程序开发门槛比较低,但其中基本的运行机制和原理还是要懂的。“比如我在面试的时候问到一个关于小程序的问题,问小程序有window对象吗?他说有吧”,但其实是没有的。感觉他并没有了解小程序底层的一些东西,归根结底来说应该只能算会使用这个工具,但并不明白其中的道理。

小程序与普通网页开发是有很大差别的,这就要从它的技术架构底层去剖析了。还有比如习惯Vue,react开发的开发者会吐槽小程序新建页面的繁琐,page必须由多个文件组成、组件化支持不完善、每次更改 data 里的数据都得setData、没有像Vue方便的watch监听、不能操作Dom,对于复杂性场景不太好,之前不支持npm,不支持sass,less预编译处理语言。

“有的人说小程序就像被阉割的Vue”,哈哈当然了,他们从设计的出发点就不同,咱也得理解小程序设计的初衷,通过它的使用场景,它为什么采用这种技术架构,这种技术架构有什么好处,相信在你了解完这些之后,就会理解了。下面我会从以下几个角度去分析小程序的运行机制和它的整体技术架构。

了解小程序的由来

在小程序没有出来之前,最初微信WebView逐渐成为移动web重要入口,微信发布了一整套网页开发工具包,称之为 JS-SDK,给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情。

但JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题,比如受限于设备性能和网络速度,会出现白屏的可能。因此又设计了一个增强版JS-SDK,也就是“微信 Web 资源离线存储”,但在复杂的页面上依然会出现白屏的问题,原因表现在页面切换的生硬和点击的迟滞感。这个时候需要一个 JS-SDK 所处理不了的,使用户体验更好的一个系统,小程序应运而生。

快速的加载

更强大的能力

原生的体验

易用且安全的微信数据开放

高效和简单的开发

小程序与普通网页开发的区别

小程序的开发同普通的网页开发相比有很大的相似性,小程序的主要开发语言也是 JavaScript,但是二者还是有些差别的。

普通网页开发可以使用各种浏览器提供的 DOM API,进行 DOM 操作,小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。

普通网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。

网页开发者在开发网页的时候,只需要使用到浏览器,并且搭配上一些辅助工具或者编辑器即可。小程序的开发则有所不同,需要经过申请小程序帐号、安装小程序开发者工具、配置项目等等过程方可完成。

小程序的执行环境

小程序架构

一、技术选型

一般来说,渲染界面的技术有三种:

用纯客户端原生技术来渲染

用纯 Web 技术来渲染

用客户端原生技术与 Web 技术结合的混合技术(简称 Hybrid 技术)来渲染

通过以下几个方面分析,小程序采用哪种技术方案

开发门槛:Web 门槛低,Native 也有像 RN 这样的框架支持

体验:Native 体验比 Web 要好太多,Hybrid 在一定程度上比 Web 接近原生体验

版本更新:Web 支持在线更新,Native 则需要打包到微信一起审核发布

管控和安全:Web 可跳转或是改变页面内容,存在一些不可控因素和安全风险

由于小程序的宿主环境是微信,如果用纯客户端原生技术来编写小程序,那么小程序代码每次都需要与微信代码一起发版,这种方式肯定是不行的。

所以需要像web技术那样,有一份随时可更新的资源包放在云端,通过下载到本地,动态执行后即可渲染出界面。如果用纯web技术来渲染小程序,在一些复杂的交互上可能会面临一些性能问题,这是因为在web技术中,UI渲染跟JavaScript的脚本执行都在一个单线程中执行,这就容易导致一些逻辑任务抢占UI渲染的资源。

所以最终采用了两者结合起来的Hybrid 技术来渲染小程序,可以用一种近似web的方式来开发,并且可以实现在线更新代码,同时引入组件也有以下好处:

扩展 Web 的能力。比如像输入框组件(input, textarea)有更好地控制键盘的能力

体验更好,同时也减轻 WebView 的渲染工作

绕过 setData、数据通信和重渲染流程,使渲染性能更好

用客户端原生渲染内置一些复杂组件,可以提供更好的性能

二、双线程模型

小程序的渲染层和逻辑层分别由 2 个线程管理:视图层的界面使用了 WebView 进行渲染,逻辑层采用 JsCore 线程运行 JS脚本。

那么为什么要这样设计呢,前面也提到了管控和安全,为了解决这些问题,我们需要阻止开发者使用一些,例如浏览器的window对象,跳转页面、操作DOM、动态执行脚本的开放性接口。

我们可以使用客户端系统的 JavaScript 引擎,iOS 下的 JavaScriptCore 框架,安卓下腾讯 x5 内核提供的 JsCore 环境。

这个沙箱环境只提供纯 JavaScript 的解释执行环境,没有任何浏览器相关接口。

这就是小程序双线程模型的由来:

逻辑层:创建一个单独的线程去执行 JavaScript,在这里执行的都是有关小程序业务逻辑的代码,负责逻辑处理、数据请求、接口调用等

视图层:界面渲染相关的任务全都在 WebView 线程里执行,通过逻辑层代码去控制渲染哪些界面。一个小程序存在多个界面,所以视图层存在多个 WebView 线程

JSBridge 起到架起上层开发与Native(系统层)的桥梁,使得小程序可通过API使用原生的功能,且部分组件为原生组件实现,从而有良好体验

三、双线程通信

把开发者的 JS 逻辑代码放到单独的线程去运行,但在 Webview 线程里,开发者就没法直接操作 DOM。

那要怎么去实现动态更改界面呢?

如上图所示,逻辑层和试图层的通信会由 Native (微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。

这也就是说,我们可以把 DOM 的更新通过简单的数据通信来实现。

Virtual DOM 相信大家都已有了解,大概是这么个过程:用 JS 对象模拟 DOM 树 -> 比较两棵虚拟 DOM 树的差异 -> 把差异应用到真正的 DOM 树上。

如图所示:

在渲染层把 WXML 转化成对应的 JS 对象。

在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到 Native,再转发到渲染层。

经过对比前后差异,把差异应用在原来的 DOM 树上,更新界面。

我们通过把 WXML 转化为数据,通过 Native 进行转发,来实现逻辑层和渲染层的交互和通信。

而这样一个完整的框架,离不开小程序的基础库。

四、小程序的基础库

小程序的基础库可以被注入到视图层和逻辑层运行,主要用于以下几个方面:

在视图层,提供各类组件来组建界面的元素

在逻辑层,提供各类 API 来处理各种逻辑

处理数据绑定、组件系统、事件系统、通信系统等一系列框架逻辑

由于小程序的渲染层和逻辑层是两个线程管理,两个线程各自注入了基础库。

小程序的基础库不会被打包在某个小程序的代码包里边,它会被提前内置在微信客户端。

这样可以:

降低业务小程序的代码包大小

可以单独修复基础库中的 Bug,无需修改到业务小程序的代码包

五、Exparser 框架

Exparser是微信小程序的组件组织框架,内置在小程序基础库中,为小程序的各种组件提供基础的支持。小程序内的所有组件,包括内置组件和自定义组件,都由Exparser组织管理。

Exparser的主要特点包括以下几点:

基于Shadow DOM模型:模型上与WebComponents的ShadowDOM高度相似,但不依赖浏览器的原生支持,也没有其他依赖库;实现时,还针对性地增加了其他API以支持小程序组件编程。

可在纯JS环境中运行:这意味着逻辑层也具有一定的组件树组织能力。

高效轻量:性能表现好,在组件实例极多的环境下表现尤其优异,同时代码尺寸也较小。

小程序中,所有节点树相关的操作都依赖于Exparser,包括WXML到页面最终节点树的构建、createSelectorQuery调用和自定义组件特性等。

内置组件

基于Exparser框架,小程序内置了一套组件,提供了视图容器类、表单类、导航类、媒体类、开放类等几十种组件。有了这么丰富的组件,再配合WXSS,可以搭建出任何效果的界面。在功能层面上,也满足绝大部分需求。

六、运行机制

小程序启动会有两种情况,一种是「冷启动」,一种是「热启动」。假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台状态的小程序切换到前台,这个过程就是热启动;冷启动指的是用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动。

小程序没有重启的概念

当小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间后(目前是5分钟)会被微信主动销毁

当短时间内(5s)连续收到两次以上收到系统内存告警,会进行小程序的销毁

七、更新机制

小程序冷启动时如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。 如果需要马上应用最新版本,可以使用 wx.getUpdateManager API 进行处理。

八、性能优化

主要的优化策略可以归纳为三点:

精简代码,降低WXML结构和JS代码的复杂性;

合理使用setData调用,减少setData次数和数据量;

必要时使用分包优化。

1、setData 工作原理

小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript 所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。

而 evaluateJavascript 的执行会受很多方面的影响,数据到达视图层并不是实时的。

2、常见的 setData 操作错误

频繁的去 setData在我们分析过的一些案例里,部分小程序会非常频繁(毫秒级)的去setData,其导致了两个后果:Android下用户在滑动时会感觉到卡顿,操作反馈延迟严重,因为 JS 线程一直在编译执行渲染,未能及时将用户操作事件传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层;渲染有出现延时,由于 WebView 的 JS 线程一直处于忙碌状态,逻辑层到页面层的通信耗时上升,视图层收到的数据消息时距离发出时间已经过去了几百毫秒,渲染的结果并不实时;

每次 setData 都传递大量新数据由setData的底层实现可知,我们的数据传输实际是一次 evaluateJavascript

脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程, 后台态页面进行 setData当页面进入后台态(用户不可见),不应该继续去进行setData,后台态页面的渲染用户是无法感受的,另外后台态页面去setData也会抢占前台页面的执行。

总结

大致从以上几个角度分析了小程序的底层架构,从小程序的由来、到双线程的出现、设计、通信、到基础库、Exparser 框架、再到运行机制、性能优化等等,都是一个个相关而又相互影响的选择。关于小程序的底层框架设计,应该还有很多,每一个框架的诞生都有其意义,我们作为开发者能做的不只是会使用这个工具,还应理解它的设计模式。只有这样才不会被工具左右,才能走的更远!

以上就是浅析小程序运行机制的详细内容,更多请关注编程之家其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


概述 消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。 订阅消息推送位置:服务通知 订阅消息下发条件:用户自主订阅 订阅消息卡片跳转能力:点击查看详情可提爱转至该小程序的页面 消息类型 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务
判断H5页面环境在微信中还是小程序中 用小程序提供的wx.miniProgram.getEnv可以获取环境参数 <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.
wx.reLaunch和wx.navigateTo,wx.navigateTo的区别 2019-03-23 11:18:05 wx.navigateTo 用于保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面。对于页面不是特别多的小程序,通常推荐使用 wx.n
微信小程序如何从数组里取值_微信小程序 传值取值的几种方法总结 小程序里常见的取值有以下几种,一个完整的项目写下来,用到的概率几乎是100%。 列表index下标取值 页面传值 form表单取值 1. 列表index下标取值 实现方式是:data-index="{{index}}&quot
H5项目接入微信授权登录,通过 UA 区分微信还是普通浏览器: let ua = navigator.userAgent.toLowerCase(); let isWeixin = ua.indexOf('micromessenge
微信小程序获取data-xx=""属性的值,自定义属性设置和获取(data-) 微信小程序<view class="details-btn" data-taskId="111" bindtap='taskdetails&#39
小程序报错:TypeError: Cannot read property ‘addEventListener‘ of undefined 解决办法 将调试基础库由2.16.0(或者当前的) -> 2.14.1 解决问题
H5跳转微信小程序-成功案例(VUE)(踩坑无数) TuoMei 已于 2022-07-29 09:52:22 修改 准备工作 根据官方提供的资料需准备以下几点: 1、已认证的服务号 2、绑定JS接口安全域名 (在微信公众平台设置) 3、IP白名单 (在微信公众平台设置) 4、将小程序和H5公众号进
微信小程序 页面跳转和数据传递实例详解 这篇文章主要介绍了微信小程序 页面跳转和数据传递实例详解的相关资料,这里附有实例代码帮助到家学习理解,需要的朋友可以参考下 微信小程序 页面跳转和数据传递 1.先导 在Android中,我们Activity和Fragment都有栈的概念在里面,微信小程序页面也
情景1.拉取公司代码演示: 因为github有墙,这里我们以gitee(码云)为例作为演示 (其实就是国产github,也非常好用~) 步骤一:打开Git界面 先在一个空文件夹右击Git Bash Here,打开git界面 步骤二:输入克隆远程仓库指令 别人复制的链接在这里获取 拿到别人赋值的链接自
如何开发微信小程序? 作为一名10多年一直从事互联网平台开发的从业者,我来回答下这个问题吧。 微信小程序开发流程总体可以归纳为4个步骤, 老张带您捋一捋整个环节,小白用户可以收藏了。 好了废话不多说,开始! 一、开发前小程序需要准备的资料 我们在开发微信小程序前,需要准备下相关资料。这个资料主要是后
原生小程序开发优化方案 为了更好的制定优化方案,我们 有必要先了解下小程序的底层架构、以及与普通网页开发的差异 小程序最终渲染载体与当下一些热门的技术 Flutter、React Native等不同,依然是浏览器内核,而不是原生客户端。 而对于传统的网页来说,UI 渲染和 JS 脚本是在同一个线程中
1,不要下两倍尺寸的图片, 小程序本身自己就会对元素缩小两倍,设计图片的一杯就已经很清晰了。 2,图片压缩,(主要是压缩静态资源,ps 可以压缩,然后有一些在线压缩工具,保持600-800kb 的静态) 3,通用的代码组件化 4,是在工程量太大可以分包,分包现在最大支持20m(一般都不会去分包的)
文章浏览阅读189次。人工智能研究实验室OpenAI在2022年11月30日发布了自然语言生成模型ChatGPT,上线两个月就已经超过一亿用户,成为了人工智能界当之无愧的超级大网红。ChatGPT凭借着自身强大的拟人化及时应答能力迅速破圈,引起了各行各业的热烈讨论。简单来说ChatGPT就是可以基于用户文本输入自动生成回答的人工智能聊天机器人。那肯定会有人说这不就是Siri嘛,虽然都是交互机器人但是两者的差别可老大了。那么ChatGPT在人机交互时为什么会有这么出色的表现?它到底会不会取代搜索引擎?90%的人真的会因为ChatG
文章浏览阅读193次。8. 导航和路由管理:掌握小程序的导航方式,如使用wx.navigateTo跳转页面、使用wx.redirect重定向页面等,学会实现页面之间的跳转和传参。1. 小程序的基本概念和架构:了解小程序的定义、特点以及与传统APP的区别,掌握小程序的运行环境、组件和API等基本概念。10. 支付功能:学习小程序的支付方式,如微信支付、支付宝支付等,了解支付流程和注意事项,学会实现小程序的支付功能。9. 用户授权和登录:了解小程序的用户授权机制,如获取用户信息、调用微信API等,学会实现用户的登录和注册功能。_微信小程序开发知识点总结
文章浏览阅读4.8k次,点赞7次,收藏18次。一、准备工作1. 安装微信开发者工具,并登录微信小程序账号;2. 准备斗地主游戏的图片资源;3. 准备斗地主游戏的音效资源;二、创建小程序1. 打开微信开发者工具,点击“新建小程序”,输入小程序名称,选择小程序的项目目录,点击“创建”;2. 在小程序的项目目录中,新建文件夹“images”,将准备好的斗地主游戏的图片资源放入“images”文件夹中;3. 在小程序的项目目录中,新建文件夹“sounds”,将准备好的斗地主游戏的音效资源放入“sounds”文件夹中;三、编写代码1. 在小程_扑克牌微信小程序代码
文章浏览阅读3.9k次,点赞3次,收藏7次。一、准备工作:1. 安装微信开发者工具,创建小程序项目;2. 准备游戏角色图片;3. 准备游戏背景音乐;二、实现步骤:1. 创建游戏页面,添加游戏角色图片,添加游戏背景音乐;2. 创建游戏角色类,定义游戏角色属性,如角色名称、角色图片、角色能力等;3. 创建游戏类,定义游戏属性,如游戏人数、游戏角色、游戏规则等;4. 创建游戏控制类,定义游戏流程,如游戏开始、游戏结束、游戏角色分配等;5. 创建游戏界面,实现游戏流程,如游戏开始、游戏结束、游戏角色分配等;6. 创建游戏结果页面,显示游戏_微信小程序游戏代码
文章浏览阅读1.7k次。1. 创建小程序项目:使用微信开发者工具创建一个小程序项目,并在项目中添加一个页面,用于模拟聊天。 2. 定义数据结构:定义一个数据结构,用于存储聊天记录,包括发送者、接收者、消息内容等信息。 3. 实现聊天功能:实现聊天功能,包括发送消息、接收消息、显示消息等功能。 4. 实现界面:使用微信小程序的界面框架,实现聊天界面,包括聊天记录列表、输入框等。代码示例:// 定义数据结构var chatData = { sender: '', receiver: '', message: '' };_制作聊天对话小程序代码
文章浏览阅读2.1k次。1、创建小程序项目:使用微信开发者工具,新建一个小程序项目,输入项目名称,选择项目目录,点击“创建”按钮,即可创建小程序项目。2、添加页面:在小程序项目中,可以添加多个页面,每个页面都有自己的页面文件,比如首页、分类页、购物车页、我的页面等。3、添加组件:在小程序项目中,可以添加多个组件,比如商品列表组件、购物车组件、订单组件等,用于在页面中显示商品信息、购物车信息、订单信息等。4、添加接口:在小程序项目中,可以添加多个接口,用于获取商品信息、购物车信息、订单信息等,以便在页面中显示。5、_微信开发者工具做一个我的商城