微信小程序运行机制解析

在微信小程序诞生之前,最流行的技术应该是Hybrid 混合开发。Hybrid 混合开发有两个优势,一是跨平台,二是热更新。而微信小程序就更像是运行在微信这个特定环境下的 Hybrid 技术。

接下来从四个方面聊一聊小程序的运行机制,看一看,小程序相比Hybrid又有哪些创新点。
相信做过微信小程序开发的小伙伴都知道,微信有一个自己开发的语言 wxs。那我们也不妨思考一下这么一个问题,既然 JavaScript 是小程序的主要开发语言,为什么微信小程序还要自己在创造一个语言呢?

一、小程序的启动机制

小程序启动会有两种情况

  • 冷启动:是指用户首次打开,或者是小程序被微信主动销毁后,再次打开,这时候小程序是需要重新加载启动

  • 热启动:假如用户已经打开过某个小程序,过了一段时间以后,用户再次去打开这个小程序,则小程序无需要再次重新启动小程序,只需要把后台运行的小程序切换到前台

这时候你可能会发现这么一个问题:小程序从本地读取缓存,那小程序什么时候可有应用新的版本呢?

小程序在冷启动时,会检测是否有新版本,如果发现有新的版本,就会异步下载新版本的代码包,并且同时用客户端本地的代码进行启动,也就是新版本的小程序,需要等到下一次冷启动时才会用上。如果你需要马上用上新的版本,则可以使用 wx.getUpdateManager 这个接口进行更新处理

那这时候你可能还有一个问题:微信什么时候主动销毁我们的小程序呢?

这里有两种情况,微信会主动销毁我们的小程序:

  1. 小程序在后台运行超过一定的时间,目前大概是五分钟
  2. 当短时间内,目前是5s 连续上次以上收到系统内存的警告(运行内存不足,请重新打开该小程序 )
    当然了,这种情况对用户体验是非常不友好的,必要的时候,我们也可以使用wx.onMemoryWarning 接口监听内存的警告事件,提请做一些处理

二、小程序的两种状态

  • 前台状态:小程序启动以后,界面被展示给用户,此时小程序处于前台状态
  • 后台状态:当用户点击右上角按钮关闭小程序,或者离开微信时,小程序并不会立刻终止运行,小程序还会再运行一段事件,这时处于后台状态。
    这种状态有点类似于浏览器的tab页,没有关闭,只是被切换了

三、小程序的双线程架构

为了安全和管控,小程序使用双线程执行:视图线程和逻辑线程

  • View 视图线程:主要提供各类组建、渲染界面

  • App Service 逻辑线程:提供 API 处理业务逻辑

两个线程都是通过底层的 WeiXinJSBridge 进行通讯

接下来我们可以通过下面几个问题来理解一下小程序的运行原理

  1. 小程序怎么实现视图更新的?
    简单来说,它是通过 setData 来实现的
    在Hybrid 应用中,是通过一个叫 evaluateJavaScript() 的方法来执行js的,在这个方法还可以通过回调获得js 方法的返回值

    webView.evaluateJavaScript("javascript: main()", 
      new ValueCallback<string>() {
        @override
        public void onReceiveValue(String value) {
          ...
        }
      }
    )
    

    在程序中,视图层和逻辑层的数据传输,实际上都是通过底层的 WeixinJSBridge,通过原生 evaluateJavaScript 实现的。
    setData 要求更新的数据首先会将这个数据转化成字符串,接着将这个字符串于代码拼接成JavaScript 脚本,最后,把拼接的内容传给 evaluateJavaScript() 去执行。
    当然小程序在视图更新上也是有做 虚拟 DOM 的优化的。所以从数据到达视图层的更新,并不是实时进行的

  2. setData可能遇到的“坑”?
    从前面我们可以看到,视图线程和逻辑线程是分开的,两个线程之间通过前置的 setData 方法来驱动数据交换,还要通过 WeixinJSBridge 进行中转,这个中转的效率是非常低的。所以有时候安卓用户在进行界面滑动时,可能会感觉到页面卡顿,这是因为视图线程一直在努力进行渲染,逻辑层发来的更新请求被阻塞了,当这种阻塞达到200ms 以上时,视图渲染便会卡顿,卡顿不仅仅和更新的频率相关,和更新的数据量也有关系,当setData更新大列表数据时,或者更新一个size很大的图片时,也容易造成卡顿。为什么只说安卓呢?安卓用户表示IOS就不会出现这种情况吗?在iOS中,小程序的页面是由多个WKWebView组成的,在系统内存紧张时,一部分WKWebView 会被系统内存回收掉,也就是说之前打开过的小程序界面,会退出历史记录,这些页面我们是无法回收的

四、微信是怎么实现视图线程与逻辑线程的?

与小程序的视图线程相关的编译器有两个,

  • wcc 编译器:wccWXML 的编译器,主要功能是将 WXML 文件编译成 JavaScript 代码

  • wcsc 编译器:wcscWXSS 编译器,主要是负责将 WXSS文件编译成JavaScript代码
    小程序的视图层是在 Polymer 框架的基础之上,基于 WebComponent 标准实现的。小程序的视图渲染有点类似与 VueDOM 渲染,都是通过 虚拟DOM 来实现的。不同的是,小程序除了一般视图组件,还有原生组件,小程序将一般视图组件放在下面,将解析后的原生组件放在上面
    小程序逻辑线程的实现,我们可以从它的生命周期来体会,
    小程序的主要生命周期有以下五个:
    onLoadonShowonReadyonHideonUnload

    当一个小程序页面启动时,首先触发的是onLoadonShow生命周期函数,页面初始化装载完毕之后,Notify 通知逻辑线程逻辑线程将初始化的Data数据发给视图线程,由视图线程渲染,完成首次渲染以后,视图线程通知逻辑线程渲染完成,派发onReady事件,监听到这个事件,代表着也没你可以进行交互了。
    此时,视图进入持续渲染状态,在运行状态下,用户触发了更新事件,如输入等操作,会触发逻辑线程的事件函数,可能触发了setData(),又向视图线程发送更新数据,视图线程再次执行更新,当用户跳转到其他小程序或者离开微信时,小程序进入后台状态,此时逻辑线程派发onHide事件。而当后台切入前台时,又会从onShow事件开始走,如果页面页面被销毁,则会派回onUnload事件

微信为什么要打造一个WXS语言?

WXSweinxinScript 的缩写,它结合WXML 可以构造出页面的组件结构,WXS不依赖于运行时的基础库版本,可以在所有版本的微信小程序里运行,WXSJavaSript是不同的语言。虽然 WXS 也是逻辑代码,但是它不是运行在逻辑线程里的,它是运行在视图线程里的,通过直接操作视图数据,避免了跨线程的通讯开销。(这时聪明的你就已经发现了,高贵的苹果用户,运行 WXS 的速度就要比安卓的快一些了。)微信打造 WXS 主要是小程序的双线程架构在数据更新上有性能瓶颈,所有才打造了WXS,虽然 WXS 可以提交视图数据的更新效率,但是,他也不是没有缺陷的,它存在以下这些问题:

  • WXS 运行环境和其他JS代码是隔离的,因此,WXS是不可以调用JavaScript 代码里定义的函数的,也是不可以调用小程序提供的wx 开头的 API接口
  • WXS 函数不能作为视图模板中的事件回调句柄。
  • 由于设备的差异,WXS 在iOS设备上运行速度要比JS快,大约是2-20倍,但是在安卓设备上,两者几乎没有差异

总结

小程序采用的是双线程架构,一个线程负责视图的渲染,另一个负责业务逻辑的处理。连个线程都是通过 WeixinJSBridge 与微信Native 底层进行通讯。两个线程之间进行的事件与数据的交互,也是通过WeixinJSBridge来完成的。所有的平台能力和硬件能力,也是通过 WeixinJSBridge 间接提供的。由于 setData 在频繁更新数据和大数据更新上存在性能瓶颈,影响渲染效率,所以微信就引入了 WXS 变成语言。一般开发时我们可以这样处理,一开始,从后端接口接收回来的初始化数据,在页面onLoad 之前,就存放到 Data 数据中,用于视图的初始化渲染,后续的是视图交互与更新,如果不与后台有关,我们就使用WXS 直接在视图中进行完成,这样可以提高渲染性能。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值