https://docs.taro.zone/blog/2020-01-02-gmtc/#%E6%96%B0%E6%9E%B6%E6%9E%84-taro-next-%E7%9A%84%E9%80%82%E9%85%8D%E4%B8%8E%E5%AE%9E%E7%8E%B0 小程序架构 微信小程序主要分为 逻辑层 和 视图层,以及在他们之下的原生部分。逻辑层主要负责 JS 运行,视图层主要负责页面的渲染,它们之间主要通过 Event 和 Data 进行通信,同时通过 JSBridge 调用原生的 API。这也是以微信小程序为首的大多数小程序的架构。 由于原生部分对于前端开发者来说就像是一个黑盒,因此,整个架构图的原生部分可以省略。同时,我们我们对 逻辑层 和 视图层 也做一下简化,最后可以得到小程序架构图的极简版: 也就是说,只需要在逻辑层调用对应的 App()/Page() 方法,且在方法里面处理 data、提供生命周期/事件函数等,同时在视图层提供对应的模版及样式供渲染就能运行小程序了。这也是大多数小程序开发框架重点考虑和处理的部分。 Taro 2.0 架构 Taro 当前的架构主要分为:编译时 和 运行时。 编译时主要是将 Taro 代码通过 Babel 转换成 小程序的代码,如:JS、WXML、WXSS、JSON。 运行时主要是进行一些:生命周期、事件、data 等部分的处理和对接。 Taro 编译时 有过 Babel 插件开发经验的应该对一下流程十分熟悉,Taro 的编译时也是遵循了此流程,使用 babel-parser 将 Taro 代码解析成抽象语法树,然后通过 babel-types 对抽象语法树进行一系列修改、转换操作,最后再通过 babel-generate 生成对应的目标代码。 这里我们是采用 穷举 的方式对 JSX 可能的写法进行了一一适配。 Taro 运行时 接下来,我们可以对比一下编译后的代码,可以发现,编译后的代码中,React 的核心 render 方法 没有了。同时代码里增加了 BaseComponent 和 createComponent ,它们是 Taro 运行时的核心。 BaseComponent 主要是对 React 的一些核心方法:setState、forceUpdate 等进行了替换和重写,结合前面编译后 render 方法被替换,大家不难猜出:Taro 当前架构只是在开发时遵循了 React 的语法,在代码编译之后实际运行时,和 React 并没有关系。 而 createComponent 主要作用是调用 Component() 构建页面;对接事件、生命周期等;进行 Diff Data 并调用 setData 方法更新数据。 总结 因此,整个 Taro 当前架构的特点是: 重编译时,轻运行时。 编译后代码与 React 无关:Taro 只是在开发时遵循了 React 的语法。 直接使用 Babel 进行编译:这也导致当前 Taro 在工程化和插件方面的羸弱。 Taro 3.0 的适配与实现 这一次,我们站在浏览器的角度来思考前端的本质:无论开发这是用的是什么框架,React 也好,Vue 也罢,最终代码经过运行之后都是调用了浏览器的那几个 BOM/DOM 的 API ,如:createElement、appendChild、removeChild 等。 我们创建了 taro-runtime 的包,然后在这个包中实现了 一套 高效、精简版的 DOM/BOM API。然后,我们通过 Webpack 的 ProvidePlugin 插件,注入到小程序的逻辑层。 这样,在小程序的运行时,就有了 一套高效、精简版的 DOM/BOM API。 React 实现 在 React 16+ ,React 的架构如下: reconciler 调解员 最上层是 React 的核心部分 react-core ,中间是 react-reconciler,其的职责是维护 VirtualDOM 树,内部实现了 Diff/Fiber 算法,决定什么时候更新、以及要更新什么。 而 Renderer 负责具体平台的渲染工作,它会提供宿主组件、处理事件等等。例如 React-DOM 就是一个渲染器,负责 DOM 节点的渲染和 DOM 事件处理。 因此,我们实现了 taro-react 包,用来连接 react-reconciler 和 taro-runtime 的 BOM/DOM API: 具体的实现主要分为两步:

  • 实现 react-reconciler 的 hostConfig 配置,即在 hostConfig 的方法中调用对应的 Taro BOM/DOM 的 API。
  • 实现 render 函数(类似于 ReactDOM.render)方法,可以看成是创建 Taro DOM Tree 的容器。 经过上面的步骤,React 代码实际上就可以在小程序的运行时正常运行了,并且会生成 Taro DOM Tree,那么偌大的 Taro DOM Tree 怎样更新到页面呢? 首先,我们将小程序的所有组件挨个进行模版化处理,从而得到小程序组件对应的模版,然后,我们会:基于组件的 template,动态 “递归” 渲染整棵树。 整个 Taro Next 的 React 实现流程图如下: 事件​ 首先的 Taro Next 事件,具体的实现方式如下: Taro Next 事件本质上是基于 Taro DOM 实现了一套自己的事件机制,这样做的好处之一是,无论小程序是否支持事件的冒泡与捕获,Taro 都能支持。 更新​ 无论是 React 还是 Vue ,最终都会调用 Taro DOM 方法,如:appendChild、insertChild 等。 这些方法在修改 Taro DOM Tree 的同时,还会调用 enqueueUpdate 方法,这个方法能获取到每一个 DOM 方法最终修改的节点路径和值,如:{root.cn.[0].cn.[4].value: "1"},并通过 setData 方法更新到视图层。 可以看到,这里更新的粒度是 DOM 级别,只有最终发生改变的 DOM 才会被更新过去,相对于之前 data 级别的更新会更加精准,性能更好。 新架构特点​ 和之前的架构不同,Taro Next 是 近乎全运行。 新的架构基本解决了之前的遗留问题: 无 DSL 限制:无论是你们团队是 React 还是 Vue 技术栈,都能够使用 Taro 开发 模版动态构建:和之前模版通过编译生成的不同,Taro Next 的模版是固定的,然后基于组件的 template,动态 “递归” 渲染整棵 Taro DOM 树。 新特性无缝支持:由于 Taro Next 本质上是将 React/Vue 运行在小程序上,因此,各种新特性也就无缝支持了。 社区贡献更简单:错误栈将和 React/Vue 一致,团队只需要维护核心的 taro-runtime。 基于 Webpack:Taro Next 基于 Webpack 实现了多端的工程化,提供了插件功能。 性能优化​ 前面提到,同等条件下,编译时做的工作越多,也就意味着运行时做的工作越少,性能会更好。Taro Next 的新架构变成 近乎全运行 之后,花了很多精力在性能优化上面。 再这之前。可以先看一下 Taro Next 的流程和原生小程序的流程对比。 可以发现,相比原生小程序,Taro Next 多了红色部分的带来的性能隐患,如:引入 React/Vue 带来的 包的 Size 增加,运行时的损耗、Taro DOM Tree 的构建和更新、DOM data 初始化和更新。 而我们真正能做的,只有绿色部分,也就是:Taro DOM Tree 的构建和更新、DOM data 初始化和更新。 包Size 我们在前面一再强调:和之前模版通过编译生成的不同,Taro Next 的模版是固定的,然后基于组件的 template,动态 “递归” 渲染整棵 Taro DOM 树。也就是说,Taro Next 的 WXML 大小是有上限的。 DOM Tree​ 在 Taro DOM Tree 的构建和更新阶段,我们实现了一套仅实现了高效的、精简版 DOM/BOM API,而且仅仅实现了必要的。 Update Date​ 在数据更新阶段,首先前面有提到过,Taro Next 的更新是 DOM 级别的,比 Data 级别的更新更加高效,因为 Data 粒度更新实际上是有冗余的,并不是所有的 Data 的改变最后都会引起 DOM 的更新。 其次,Taro 在更新的时候将 Taro DOM Tree 的 path 进行压缩,这点也极大的提升了性能。 性能优化——预渲染(Prerender) Taro 预渲染的工作原理是,在构建阶段使用服务器端渲染(SSR)的技术,将页面组件渲染成静态 HTML 文件,并将其保存在静态文件目录中。然后,当客户端请求该页面时,直接返回预渲染的静态 HTML,而不是动态生成页面。 通过在构建阶段将页面渲染为静态 HTML 文件,以提升首次加载速度、改善用户体验和优化搜索引擎的索引。

补充

补充:Taro 是京东出品的跨端开发框架,支持用 React/Vue 语法一次编写,编译到微信、支付宝、字节、QQ、百度、钉钉等小程序以及 H5、RN。

关键要点:

  • 架构演进:Taro 1/2 重编译时(用 Babel 把 JSX 编译为小程序模板);Taro 3 改为「自定义运行时 + taro-runtime」,模拟浏览器 BOM/DOM,框架运行在小程序逻辑层。
  • 性能优化:在 DOM Tree 构建、Update Data 压缩、PreRender 等环节做了大量优化,体积和启动速度比 2.x 显著改善。
  • 新架构特点:无 DSL 限制(React/Vue 都可)、模板动态构建、新特性无缝支持、错误栈与原生一致。

补充:Taro Next 引入了 Webpack 5 + rspack,进一步提升构建速度;如果项目以 React + TypeScript 为主,Taro 是较成熟的选择。