基于Taro Next(React)的微信小程序渲染

Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5 等应用。
本篇文章重点关注基于Taro Next(React)的微信小程序渲染,主要将从以下几个方面进行:

  • 浏览器渲染流程
  • React 渲染流程
  • 微信小程序渲染流程
  • 基于Taro Next(React)的微信小程序渲染流程
  • 基于Taro Next(React)的微信小程序渲染问题和解决方案

浏览器渲染流程

Web Rendering

用户通过在地址栏输入一个网站的URL后,内容显示到浏览器的完整过程

  1. 浏览器查看是否需要redirect, 如果需要,则redirect到对应url
  2. 查看是否命中缓存,如果有直接到7,如果没有继续3
  3. 解析域名,进行DNS查找
  4. 创建http(s)连接
  5. 开始发送请求
  6. 接收服务端响应
  7. 解析处理HTML标记并构造DOM树
  8. 预加载扫描仪将解析可用的内容并请求高优先级资源,如CSS、JavaScript和web字体
  9. 解析处理CSS并构建CSSOM树
  10. 下载其他资源。当CSS被解析并创建CSSOM时,其他资源,包括JavaScript文件正在下载。JavaScript被解释、编译、解析和执行。
  11. CSSOM树和DOM树组合 创建一个Render树。Render树保存所有具有内容和计算样式的可见节点
  12. 在Render树上运行布局以计算每个节点的几何体
  13. 将各个节点绘制到屏幕上,在绘制或光栅化阶段,浏览器将在布局阶段计算的每个框转换为屏幕上的实际像素
  14. 合成文档中不同的层,以确保相互重叠层以正确的顺序绘制到屏幕上,并正确显示内容

React 渲染流程

React Render

JSX 会被编译转换成 React.createElement 函数的调用,其返回值就是 VNode(JS对象),虚拟DOM节点的描述对象。

  1. 在首次渲染时,所有组件会创建对应的VNode
  2. React 将 React.render 接收到的 VNode 转化虚拟 DOM 树
  3. 根据虚拟 DOM 树的层级关系,构建生成出 DOM 树并渲染至屏幕中
  4. 状态改变时,通过diff算法对比2课虚拟DOM树,得到差异(patches)
  5. 将差异应用到DOM树上,并将变化更新到屏幕中(进行重新渲染)

Note: Fiber 是 React 16 中新的协调引擎。它的主要目的是使 Virtual DOM 可以进行增量式渲染。了解更多.

对于首次渲染,React 的主要工作就是将 React.render 接收到的 VNode 转化 Fiber 树,并根据 Fiber 树的层级关系,构建生成出 DOM 树并渲染至屏幕中。

而对于更新渲染时,Fiber 树已经存在于内存中了,所以 React 更关心的是计算出 Fiber 树中的各个节点的差异,并将变化更新到屏幕中。

微信小程序渲染流程

MINA 是在微信中开发小程序的框架。其目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。

MINA 提供了自己的渲染层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,核心是一个响应的数据绑定系统。

小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。

小程序的渲染层和逻辑层分别由2个线程管理:

  • 渲染层的界面使用了WebView 进行渲染
  • 逻辑层采用JsCore线程运行JS脚本

一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型下图所示


WeChat Mini Program

渲染过程:

  • 在渲染层,宿主环境(微信App)会把WXML转换成对应的JS对象(可以看作与React的VNode)
  • 将JS对象再次转换成真实DOM树,交由渲染层线程渲染(Weview初始化完成后的流程与浏览器渲染流程一致)
  • 数据变化时(在小程序容器中,逻辑层到渲染层的更新,只能通过 setData() 来实现。),逻辑层提供最新的变化数据,生成新的JS对象与之前的JS对象进行diff算法对比
  • 将最新变化的内容反映到真实的DOM树中,更新UI

基于Taro Next(React)的微信小程序渲染流程

从实现原理上,开源社区的跨端框架大致分为下面两类:

  • compile time 编译时
    框架约定了一套自己的 DSL ,在编译打包的过程中,利用 babel 工具通过 AST 进行转译,生成符合小程序规则的代码,如Taro v1/2
  • runtime 运行时
    跨端框架真正的在小程序的逻辑层中运行起 React 或者是 Vue 的运行时,然后通过适配层,实现自定义渲染器,如Taro Next

React 16版本带来了全新的 fiber 的架构,代码拆分也非常清晰,大体上可以拆分成这三大块:

  • React component API
  • Reconciler
  • Renderer

其中渲染器Renderer负责将内容渲染到具体的平台上。最常见的 ReactDOM 就是 web 浏览器平台的自定义渲染器。即当调用操作 WEB 浏览器 web DOM的方法,如createElement、appendhild,那么就创建/更新浏览器中的 web 页面。

扩展阅读,【2万字长文】深入浅出主流的几款小程序跨端框架原理

在一个页面加载时需要经历以下步骤:

  • React把页面渲染到虚拟 DOM 中
  • Taro 运行时把页面的虚拟 DOM 序列化为JSON 树状数据,并使用 setData() 驱动页面渲染
  • 小程序本身渲染序列化数据,渲染到小程序页面
  • 数据变化时,通过setData()去更新上面小程序的 JSON 树状数据
  • JSON 树状数据被更新了,小程序会触发更新数据对应的那块视图的渲染

基于Taro Next(React)的微信小程序渲染问题和解决方案

和原生小程序或编译型小程序框架相比,基于Taro Next(React)的微信小程序渲染流程中的步骤 1 和 步骤 2 是新增的。如果页面的业务逻辑代码没有性能问题的话,大多数性能瓶颈出在步骤 2 的 setData() 上。
由于初始化渲染是页面的整棵虚拟 DOM 树,数据量比较大,因此 setData() 需要传递一个比较大的数据,导致初始化页面时会一段白屏的时间。这样的情况通常发生在页面初始化渲染的 wxml 节点数比较大或用户机器性能较低时发生。

解决方案:

  1. 多使用stateless component
  2. stateful component在setData的时候减小数据量
  3. 正确使用hooks dependencies, 并减少 setData 函数的调用次数
  4. Taro 3 官方也提供了一些种方式:

参考文档:
https://developer.mozilla.org/zh-CN/docs/Web/Performance/How_browsers_work
https://reactjs.org/docs/rendering-elements.html#gatsby-focus-wrapper
https://reactjs.org/docs/reconciliation.html
http://yunlaiwu.github.io/blog/2017/08/14/react-virtual-dom-fiber/
https://juejin.cn/post/6923073253988810765
https://zhuanlan.zhihu.com/p/103506207
https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/framework.html
https://developers.weixin.qq.com/miniprogram/dev/framework/MINA.html
https://juejin.cn/post/6881597846307635214
https://juejin.cn/book/6844733744830480397
https://taro-docs.jd.com/taro/docs/optimized
https://docs.taro.zone/blog/2021-02-08-taro-jxpp

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352