各小程序框架实现思路学习记录
发表时间:2021-1-5
发布人:葵宇科技
浏览次数:79

小程序
已知,网页是单线程工作的,即是渲染进程在工作时,假如 JavaScript 引擎 执行 JavaScript 代码时,渲染进程会将控制权交予 JavaScript 引擎,不会两个进程同时在工作。因为,JavaScript 引擎 可能会操作DOM,所以,为了排除冲突,确保渲染正确,网页是单线程工作的。
但是,小程序,是双线程工作的。它分为逻辑层跟视图层。他们通过线程通信,共同完成视图的完整呈现和交互。此外,小程序不提供操作视图层的元素的方法,所以它无法像网页那样用 JavaScript 去操作 DOM 元素去实现更新。
引自:小程序的运行环境
各平台脚本执行环境以及用于渲染非原生组件的环境是各不相同的:
在 iOS 上,小程序逻辑层的 javascript 代码运行在 JavaScriptCore 中,视图层是由 WKWebView 来渲染的,环境有 iOS 12、iOS 13 等;
在 Android 上,小程序逻辑层的 javascript 代码运行在 V8 中,视图层是由自研 XWeb 引擎基于 Mobile Chrome 内核来渲染的;
在 开发工具上,小程序逻辑层的 javascript 代码是运行在 NW.js 中,视图层是由 Chromium Webview 来渲染的。
视图层的实现是 webView ,但这是一个定制 webView ,它不能运行 JavaScript ,且内容也不是 html 。
那么,小程序为什么要实现双线程工作呢?官方回答如下:
- 快速的加载
- 更强大的能力
- 原生的体验
- 易用且安全的微信数据开放
- 高效和简单的开发
但,这个见仁见智吧。
Mpvue
在小程序整出一套 wxml wxss wxs 的组合拳时,其实是在给开发者增加负担。那有没有一种方案,是用自己熟悉的框架的语法去写,但是产出却是小程序呢?办法总是有的,Mpvue 先行一步。其实 vue runtime 并不涉及 DOM 的修改,它就是一整套的 JavaScript 方法,可以愉快地运行在小程序的逻辑层。所以 Mpvue 复制了一套 Vue 库出来改造一下去实现这个伟大的目标。
实现原理如下:
// 这是 Vue 的实现
// template -> AST -> render -> vnode -> patch -> DOM
// ^
// /
// /
// js ---------> new Vue()
// 这是 Mpvue
// template -> AST -> render -> vnode -> patch -/-> DOM
// ^ |
// / |
// / V
// js ---------> new Vue() ---> setData
// \ /
// \-> page() /
//
复制代码
在创建 Vue 示例的时候,调用 page 方法,经过 Vue 处理后并不patch到DOM去渲染,而是通过 setData 去更新小程序实例上的数据,从而更新小程序的视图(因为小程序分了逻辑层和视图层,所以小程序并没有提供操作小程序节点的 API 方法)。
引自:【2万字长文】深入浅出主流的几款小程序跨端框架原理
小程序平台还规定,要在小程序页面中调用
Page()方法生成一个page实例,Page()方法是小程序官方提供的 API。(解答为什么需要调用 page 方法)
此外,Vue模板转小程序模板,生命周期对齐,事件处理等暂且不说。大体的实现原理就这些。
总结:
类Vue的小程序框架实现原理关键点:
- 实例化时,调用
page方法 - 更改
Vue流程,使用setData来替代DOM操作 Vue模板转小程序模板,生命周期对齐,事件处理等
Taro 1 & 2
React 比 Vue 难处理的点在于,React 开发是非模板化的,使用了 jsx ,导致它太灵活了,不好圈定范围去转化为小程序的模板(我们知道模板转化主要是靠AST来完成的,有限的范围可以更好地处理)。
但 Taro 还是啃下了这块硬骨头,当然,不是那么容易和愉快。限制很多,开发只是类 React 。
Taro 通过穷举法将类 React 的组件和元素,通过AST转化为小程序的模板,加上不管是类Vue还是类React的小程序框架都要做的事情:生命周期对齐,事件处理等,就这样,啃下了这块硬骨头。
总结:
主要是靠 AST 穷举完成模板转化(核心),除了拥有了 React 开发时的爽度外,React 的其他优势无法利用。但无论如何也是值得鼓励和称赞。
Remax & Taro Next
如同 Mpvue 先行者,Remax 在 React 类小程序框架也迈出了重要的一步。
Remax 的口号是,使用真正的、完整的 React 来开发小程序 。
它是怎么达成这个目标的呢?请看下面的流程分析:
// Remax 分析
// ----------------------------------------------------
// --------------| react reconciliation |--------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// ---------------| vNode and Effect List |------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// ----------------| Remax vNode (json) |--------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// --------------| miniProgrom setData |---------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// ----------------| miniProgrom data |----------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// -------------------| base.wxml |--------------------
// -------------------------|--------------------------
// ---------------------( 递归遍历 )---------------------
// -------------------------|--------------------------
// -------------------------V--------------------------
// --------------------| 页面 / 组件 |-------------------
复制代码
Remax 可以分为两个部分,一个是 react runtime ,包含 react 的除 render 之外的核心内容;另一部分就是 Remax 实现的渲染器。
引自:Remax 实现原理
Remax 的运行时本质是一个通过
react-reconciler实现的一个小程序端的渲染器。
直白点,**Remax的核心大约是 React reconciliation + Remax 渲染器 + base.wxml **。
解释一下这:
React reconciliation负责更新节点和更新时机,产出是vnode;Remax 渲染器,将以上产出的vnode从原本应该渲染为DOM的操作改为生成/更新自身vnode树(此vnode跟react的vnode不同,是Remax创建的vnode),产出是Remax vnode;- 调用
setData方法,让小程序更新数据,从而将Remax vnode传递到小程序中,然后小程序根据data和base.wxml递归渲染出页面来。
总结:
Remax 和 Taro Next 实现思路是一致的,真正地让 React 运行时在小程序的逻辑层跑起来了,从而拥有比较完整的React开发体验。
实现的基础条件是,小程序的 template 支持动态递归渲染。
实现核心在于,Remax 渲染器将 React 运行时产出的 vnode 转化为 Remax vnode,从而拥有一颗完整的节点树。然后数据 + template 动态递归渲染,渲染出页面来。
类 Vue 小程序框架和拥有完整体验的类 React 小程序框架的实现思路对比
从上文可以看到,类 Vue 小程序框架的实现思路是 **Vue 运行时 + AST 转化小程序模板 **。
而拥有完整体验的类 React 小程序框架实现的思路是 React 运行时 + 运行在内存中的由各个框架维护的 vnode 树(非 VDOM 的 vnode) + 静态模板。
看起来,类 Vue 小程序框架的实现思路更胜一层,但其需要对Vue框架进行一定的改造,所以会比较依赖 Vue。
而拥有完整体验的类 React 小程序框架,有 React 的完整开发体验(这也很重要),但无法利用 React 的调度,是递归地渲染(这和 React 以前无调度版本很相似)。且有一个必要的基础条件,就是微信小程序的 template 支持动态递归(这是 Remax 的地基)。








