小程序技术原理

308 阅读4分钟

小程序的双线程设计

image.png WebView + JsBridge

小程序分为渲染层(由WebView线程管理)和逻辑层(由客户端JavaScript解释引擎线程管理)

Web技术是非常开放灵活的,开发者可以利用JavaScript脚本随意地操作DOM,危害用户的网站的安全。

双线程设计:

  1. 可以防止恶意攻击者的XSS攻击
  2. 可以防止开发者恶意盗取用户敏感信息。
  3. 提升页面加载性能 痛点:
  4. 浏览器中的DOM、BOM等对象和API,都无法在小程序中使用
  5. 小程序的一些API使用方式与浏览器行为不一致(请求、资源等)
  6. 逻辑层和渲染层的通信依赖客户端进行通信,当通信过于频繁,可能会导致性能问题。

双线程的通信设计

在小程序中,不管是逻辑层还是渲染层,都是用 微信客户端Native 进行直接通信,同时用于与其他模块或者外部进行中转通信。

1.虚拟DOM设计

  1. 在渲染层里,把WXML转化成对应的用于描述 虚拟DOM树的JS对象
  2. 在逻辑层发生数据变更的时候,通过宿主环境提供的setData 方法,把变更从逻辑层传递到Native,再转发到渲染层
  3. 在渲染层里。经过对比前后差异,把差异应用在原来的Virtual DOM 树上,更新界面

2.Shadow DOM模型(shadow Root、shadow Tree)

什么是 Shadow Tree

Web components 是一个重要属性是封装:可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。

Web Component中的三项技术

  • Custom elements 自定义元素
  • Shadow DOM 影子DOM
  • HTML template HTML 模板

其中,shadow DOM 接口是关键所在,它可以将一个隐藏的、独立的DOM 附加到一个元素上。

渲染层渲染过程

初始渲染

渲染层在接收到初始数据(data)时,需要进行渲染层渲染。

  • 初始渲染时,将初始数据套用在对应的 WXML 片段上生成节点树。
  • 初始渲染中得到的 data 和当前节点树会保留下来用于重渲染。

减少 WXML 中节点的数量,可以有效降低初始渲染和重渲染的时间开销,提升渲染性能。

重渲染

渲染层在接受到更新数据时(setDate 数据)时,需要进行渲染层渲染。

虚拟DOM设计

  1. 每次重渲染时,将data和setData数据套用在WXML片段上,得到一个新节点树。
  2. 将新节点树与当前节点树进行比较,这样可以得到哪些节点的哪些属性可以更新、哪些节点需要添加或移动。
  3. 最后,将setData 数据合并到data中,并用新节点树替换旧节点树,用于下一次重渲染。

去掉不必要设置的数据,减少setData 的数据量也有助于提升这一个步骤的性能。

自定义组件的渲染?

Shadow-Tree

  1. 逻辑层新建组件,并通知渲染层

    • 逻辑层:
      1. 首先WXML 和 JS 需要生成一个 JS 对象。
      2. 然后JS的结点部分生成 Virtual DOM 信息。
      3. 最后通过底层通信通知到渲染层。
    • 渲染层
      1. 拿到 Virtual DOM 节点信息
      2. 创建 Shadow DOM ,拼接 Shadow Tree
      3. 注入初始数据渲染
  2. 逻辑层调用 setData,更新数据到渲染层

    逻辑层执行逻辑,调用setData之后,会在逻辑层进行 DOM diff,然后将Diff 结果传到渲染层。(注意此处与之前的渲染流程不一致)

  3. 渲染层组件更新

    渲染层拿到 diff 信息,更新 Virtual DOM 信息,同时更新页面

原生组件的同层渲染

由于原生组件脱离在WebView 渲染流程外,导致原生组件层级最高

image.png

同层渲染:小程序通过某种hack方式将原生组件插入可控层级,使得原生组件的层级和非原生组件一样可控,从而解决了遮挡的问题。