美文网首页
小程序底层原理及渲染机制

小程序底层原理及渲染机制

作者: DY_alley | 来源:发表于2023-09-06 14:13 被阅读0次

一、小程序的渲染方式

  • web技术渲染
  • Native技术渲染
  • Hybrid技术渲染(同时使用webview和原生进行渲染)

微信小程序是以webview渲染为主,原生渲染为辅的混合渲染方式

支付宝小程序是以webview渲染为主,原生渲染为辅的混合渲染方式,但是也提供了 原生为主 webview为辅的这种方式

为什么小程序不采用纯原生 或者 纯web技术进行渲染

1、首先从小程序的定位上来讲, 它就不可能用纯原生技术进行开发,因为那样它的编译以及发版都需要跟随App的版本,
所以需要像web技术那样,有一份随时可更新的资源包放在远程,通过下载到本地,动态执行后即可渲染出页面

2、如果采用纯web技术开发的话 会有一个狠致命的缺点,那就是在web技术中 UI渲染跟Javascript的脚本执行都在一个
单线程中执行,这就容易导致一些逻辑任务抢占UI渲染的资源。这也就跟设计之初的快相违背了

3、因此小程序采用了Hybrid技术,界面主要由成熟的web技术渲染,接口提供丰富的客户端原生交互能力, 同时每个小程序页面都是用不同的webview去渲染,这样可以提供更好的交互体验。也避免了单个webview的任务过于繁重

二、小程序的核心

小程序是一个双线程 、多webview的架构
渲染层: 渲染层的界面使用了webview进行渲染
逻辑层:逻辑层采用JSCore线程执行JS脚本

视图层和逻辑层通过系统层的JSBridage进行通信,小程序存在多个界面,所以渲染层存在多个webView线程
逻辑层和渲染层通信由Native做中转,逻辑层发送网络请求也会经过Native转发

优势:

  • Service 和 View的分离和并行实现可以防止JS执行影响/减慢页面渲染,有助于提高渲染性能

  • JS在Service层执行,所以JS里面操作的DOM将不会对View层产生影响,所以小程序不能操作DOM结构,这也就使小程序性能比传统的H5更好

缺点: 无处不在的异步问题(但是小程序的生命周期解决了这个问题 )

三、 双线程模型的由来

浏览器的渲染模型:

浏览器是一个单线程框架,主要是因为JS允许访问操作DOM,因此JS线程和渲染线程只能互斥运行
小程序做双线程的原因是因为小程序禁止JS操作DOM

由于javascript的灵活性和浏览器的功能比较丰富 会导致很多不可控的隐私,因此微信提供了一个单纯的JS执行环境。只提供JS的解释执行环境,类型于HTML5中的ServiceWorker 、webWorker。这两者都是启用另一个线程来执行JS。

但是考虑到小程序是一个多webview的架构,每个小程序的页面都是不同的webview,在这个架构下我们不好去用某个webview中的ServiceWorker去管理所有的小程序页面。因此我们需要使用客户端系统有Javascript的解释引擎

IOS:

在IOS下面是用内置的JavascriptCore框架

Android:

腾讯X5内核提供的JSCore环境

这样我们就可以创建一个单独的线程去执行Javascript 这个环境下执行的都是有关小程序业务逻辑的代码。也就是我们一直提到的逻辑层,而界面渲染相关的任务都在webview线程里执行

四、设计思路-渲染层

标签实现

小程序使用的是Exparser组件模型,Exparser组件模型与web Components中的shadow DOM高度相似,小程序使用自定义组件框架 而不是使用web Components 主要是因为出于安全考虑 并且方便管控。

shadow Dom

shadow Dom是web Components的一个很重要的属性封装,可以将标记结构 样式、和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起
可使代码更加干净 整洁。shadow DOM接口的关键是在于 它可以将一个隐藏且独立的DOM附加到一个元素上

shadow DOM允许将隐藏的DOM树附加到常规的DOM树中 它以shadow root节点为起始根节点在根节点的下方可以是任意元素,和普通DOM一样(典型的video audio标签)

创建shadow DOM方式:

var shadow = Element.attachShadow({mode:'closed'});

Exparse组件模型:

Exparser组件模型参考了shadow DOM并进行了一些修改,像事件系统就是完全复刻的,Slot插槽,属性传递等都基本一致,但同时又具备一些特点:

  • 基于shadow DOM模型模型上与web components的shadow DOM高度相似,但不依赖浏览器的原生支持,也没有其他依赖库。实现时 还针对性的增加了其他API支持小程序组件编写
  • 可以在纯JS环境中运行,这意味着逻辑层也具备一定的组件树组织能力
  • 高效轻量 在组件实例极多的环境下表现尤其优异

五、设计思路-逻辑层

数据更新

小程序的视图层目前使用webview作为渲染载体,而逻辑层是独立的JSCore作为运行环境

在架构上webview和JScore都是独立的模块,并不具备数据直接共享的通道,所以在更新数据时必须调用setData来通知渲染层做更新

evaluate Javascript

视图层和逻辑层的数据传输 实际上通过两边提供的evaluateJavascript实现,即用户传输的数据,需要将其转化为字符串形式传递,同时把转换后的数据内容拼接成一份JS脚本,在通过JS脚本的形式传递到两边独立环境

因为evaluateJavascript的执行会受到很多方面的影响,数据到达视图层并不是实时的,所以我们的setData函数将数据从逻辑层发送到视图层,是异步的。

不要每次 setData 都传递大量新数据(单次stringify后不超过256kb)

流程:

  • invoke: 调用native API
  • invokeCallbackHandler: native 传递 invoke方法回调结果
  • publish: 渲染层用来向逻辑业务层发送消息,也就是说要调用逻辑层的事件方法
  • subscribe: 订阅逻辑层消息
  • subscribeHandler: 视图层和逻辑层消息订阅转发
  • setCustomPublishHandler 自定义消息转发

六、 小程序整体渲染流程

1、打开小程序 创建视图层页面的webview时,此时会初始化渲染层webview,并且将webview的view地址设置为instanceframe.html,也就是我们的渲染层模版

2、然后进入页面index/index 等instanceframe webview初始化完成后,会将页面index/index编译好的代码注入进来并执行

// 将webview src路径修改为页面路径
history.pushState('', '', 'http://127.0.0.1:26444/__pageframe__/index/index')

/*
... 
这里还有一些 wx config及wxss编译后的代码
*/

// 这里是
var decodeName = decodeURI("./index/index.wxml")
var generateFunc = $gwx(decodeName)
if (decodeName === './__wx__/functional-page.wxml') {
  generateFunc = function () {
    return {
      tag: 'wx-page',
      children: [],
    }
  }
}
if (generateFunc) {
  var CE = (typeof __global === 'object') ? (window.CustomEvent || __global.CustomEvent) : window.CustomEvent;
  document.dispatchEvent(new CE("generateFuncReady", {
    detail: {
      generateFunc: generateFunc
    }
  }))
  __global.timing.addPoint('PAGEFRAME_GENERATE_FUNC_READY', Date.now())
} else {
  document.body.innerText = decodeName + " not found"
  console.error(decodeName + " not found")
}

3、通过history.pushState方法修改webview的src但是webview并不会发送页面请求。并且将调用$gwx为生成一个generateFun方法。这个方法用来生成虚拟DOM

4、然后判断generateFun方法是否存在 通过document.dispatchEvent派发发自定义事件,generateFuncReady将generateFunc当作参数传递给底层渲染库

5、底层渲染库WAWebview.js中会监听自定义事件generateFuncReady,然后通过weixinJSBridge通知JS逻辑层视图已经准备完毕

6、最后JS逻辑层将数据给webview渲染层, WAwebview.js 在通过Virtual dom生成真实DOM。最后挂载到document.body上

相关文章

网友评论

      本文标题:小程序底层原理及渲染机制

      本文链接:https://www.haomeiwen.com/subject/adykvdtx.html