聊聊小程序运行机制的那些事(图文结合)
ccwgpt 2024-10-15 08:53 28 浏览 0 评论
小程序的由来
在小程序没有出来之前,最初微信WebView逐渐成为移动web重要入口,微信发布了一整套网页开发工具包,称之为 JS-SDK,给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情。
但JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题,比如受限于设备性能和网络速度,会出现白屏的可能。因此又设计了一个增强版JS-SDK,也就是“微信 Web 资源离线存储”,但在复杂的页面上依然会出现白屏的问题,原因表现在页面切换的生硬和点击的迟滞感。这个时候需要一个用户体验更好的一个系统,小程序应运而生。小程序主要具有以下的特点:
- 快速的加载
- 更强大的能力
- 原生的体验
- 易用且安全的微信数据开放
- 高效和简单的开发
小程序与普通网页开发的区别
小程序的开发同普通的网页开发相比有很大的相似性,小程序的主要开发语言也是 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 树上。
如图所示:
1. 在渲染层把 WXML 转化成对应的 JS 对象。
2. 在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到 Native,再转发到渲染层。
3. 经过对比前后差异,把差异应用在原来的 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 框架、再到运行机制、性能优化等等,都是一个个相关而又相互影响的选择。关于小程序的底层框架设计,其实涉及到的还有很多,比如自定义组件,原生组件、性能优化等方面,都不是一点能讲完的,还要多看源码,多思考。每一个框架的诞生都有其意义,我们作为开发者能做的不只是会使用这个工具,还应理解它的设计模式。只有这样才不会被工具左右,才能走的更远!
相关推荐
- NestJS入门教程系列一
-
介绍Nest(NestJS)是用于构建高效,可扩展的Node.js服务器端应用程序的框架。它使用渐进式JavaScript,内置并完全支持TypeScript(但开发人员仍然能够使用JavaScrip...
- 【推荐】一个网盘资源搜索与转存工具,支持移动端与PC端!
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍CloudSaver是一个基于Vue3和Express的网盘资源搜索与转存开源实用工具。它支持...
- Appium原理精讲
-
目前使用Appium新版本和旧版本的企业数目都很多,而两个版本的安装过程和api的使用又有较大的区别。但是无论表面上的东东如何变化,内部原理都是一样的。在这里我给大家介绍一下appium的核心,增进大...
- Kubernetes最小部署单元Pod
-
一、Kubernetes与Pod简介在当今云计算和容器化技术盛行的时代,Kubernetes已然成为容器编排领域的中流砥柱。它是一个开源的容器编排平台,由Google基于其内部使用的Bo...
- 最常用的四种跨域解决方案
-
前置知识什么是跨域?浏览器发送的请求地址(URL)与所在页面的地址不同(端口/协议/域名其一不同)。简言之,浏览器发出的请求url,与其所在页面的url不一样。此时,同源策略会让浏览器拒收服务器...
- Bolt.New —— 全栈AI Web自动编程
-
Bolt.New是由StackBlitz公司推出的,全栈AI工具,代码编辑、运行、部署,通通一站式搞定。它使用WebContainers技术,无需任何本地安装或配置,在浏览器中,就可以运行完整的No...
- Nodejs Express新手教程&高手进阶
-
NodejsExpress新手教程&高手进阶Express是一个NodeJS平台的框架,主要用于构于Web服务器项目。本文将通过示例介绍适合新手入门的Express基础使用,以及高手进阶知识,如:c...
- Express.js 创建Node.js Web应用
-
Express.js是一个基于Node.js的Web应用框架,框架的设计目的是构建应用的架构和简化应用的开发。框架会解决一些通用的问题,在Express.js中,Express框架会处理如:中间件、代...
- JavaScript 的 Express.js 功能及应用场景详解
-
Express.js是一个基于Node.js的轻量级Web应用框架,主要用于快速构建服务器端应用和API。它的核心功能包括以下关键点:1.路由管理URL路径与HTTP方法映射:通过...
- nodejs的express4文件下载
-
在nodejs的express框架中,下载变得非常简单,就一个方法,res.download()首先express命令行生成项目基本框架:不会的看这里:http://blog.csdn.net/zz...
- Express 系列:快速生成一个项目
-
系列预告本系列将以一个项目入手结合相关技术细节来带领大家一起学习Express这个基于Node.js的后端框架。本文首先将介绍:如何快速的生成一个具有一定结构的Express项目。Express项目结...
- nodejs的express自动生成项目框架
-
nodejs版本为:4.X,express版本为4.X1.全局安装2个模块express、express-generator在命令行输入:npminstall-gexpressnpminsta...
- express开发(一)简介与搭建
-
上周末去了趟上海书城,不愧是上海数得上号的书城,流行的科技书应有尽有,话不多说直接上图。最经典的C语言O(∩_∩)O最流行的java(づ ̄3 ̄)づ超酷的R语言/(ㄒoㄒ)/~~然而,身为一个坚定的前...
- Vue+Echarts可视化大屏系统后端框架搭建(附代码)
-
各位同学,大家好。上节课,前面我们讲解了Vue+Echarts前端部分的设计方法。这节课程,我们开始讲解使用Express进行后端设计的方法。01项目相关理论介绍什么是expressExpress是...
- Shopify电商API接口开发
-
Shopify电商API接口开发上线流程主要包括以下步骤。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎洽谈合作。前期准备-注册Shopify账号:在Shopify官网注册,用于后续开发测试...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- express框架 (43)
- scrapy框架 (52)
- beego框架 (42)
- java框架spring (43)
- grpc框架 (55)
- 前端框架bootstrap (42)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)