taro整体架构简析

如何用 React 写小程序

复制代码
// index.wxml
<view class="container">
  <view class="userinfo">
    <button wx:if="{{!hasUserInfo && canIUse}}"> 获取头像昵称 </button>
    <block wx:else>
      <image src="{{userInfo.avatarUrl}}" background-size="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto" style="color:{{color}};" >
    <text class="user-motto">{{motto}}</text>
  </view>
</view>

// app.wxss 
@import "common.wxss";
.middle-p {
  padding:15px;
}

目标:jsx -> 小程序模板

babel作为代码编译器,能将我们的代码编译成抽象语法树(AST),再将语法树通过转义(穷举,官方推荐写法、常用写法等)生成我们的目标代码

初代的taro最基本的原理就是如此,在1.x版本中专门维护了一个,这个包将react中的各种写法根据语法树转换成小程序目标代码,以此用react写小程序

taro1.0初代架构

编译时:根据配置将入口文件中的config进行遍历处理,判断页面依赖、获取页面模板并根据对应编译平台输出成对应平台的小程序文件

运行时:主要负责组件的渲染、事件处理、数据绑定(state->data)、生命周期管理以及平台兼容等一系列操作,这些都Taro通过自定框架来模拟实现,在设计的时候使用了类似react的设计概念,以便于开发者可以用类似于开发web应用的方式来开发小程序。

复制代码
1. **组件系统**: Taro 实现了一套自己的组件系统,这套系统模仿了 React 的组件模型,使得开发者可以使用类似 React 的方式编写组件和管理状态。这包括组件的生命周期管理、状态(state)和属性(props)的更新机制等。

2. **事件系统**: Taro 抽象并模拟了一套类似于 React 的事件处理系统,这包括事件的监听、响应和事件对象的封装。事件处理程序的绑定和解绑都是通过 Taro 运行时来管理的。

3. **数据绑定**: Taro 1.0 提供了一种数据绑定机制,使得组件的渲染可以依赖于状态和属性。当状态或属性发生变化时,Taro 会自动更新组件,确保视图与数据保持同步。

4.**生命周期管理**: Taro 将 React 的组件生命周期映射到小程序的页面和组件生命周期中,这样开发者能够以熟悉的方式编写代码,而 Taro 运行时则负责正确地调用这些生命周期方法。

|------------|-----|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 类型 | 阶段 | Taro | 小程序 |
| 工程目录 | 编译时 | my-project/ ├── build/ # 构建文件夹 │ ├── index.html # 主页HTML文件 │ └── index.js # 主页JavaScript文件 ├── config/ # 配置文件夹 │ ├── app.json # 应用配置文件 │ └── project.config.js # 项目配置文件 ├── node_modules/ # 第三方依赖库 ├── package.json # 包管理器配置文件 ├── src/ # 源代码文件夹 │ ├── assets/ # 资源文件夹(图片、字体等) │ ├── components/ # 组件文件夹 │ │ ├── index.js # 组件入口文件 │ │ └── MyComponent.js # 组件实现文件 │ ├── index.js # 主入口文件 │ └── pages/ # 页面文件夹 │ ├── index.js # 首页入口文件 │ └── otherPage/index.js # 其他页面入口文件 └── tools/ # 工具文件夹 ├── dev-server.js # 开发服务器配置文件 └── start-dev-server.sh # 开发服务器启动脚本 | my-wechat-app/ ├── app.json # 应用配置文件 ├── app.wxss # 样式文件 ├── app.js # 主入口文件 ├── pages/ # 页面文件夹 │ ├── index.js # 首页入口文件 │ └── otherPage/index.js # 其他页面入口文件 │ ├── otherPage.wxml # 页面组件文件 │ ├── otherPage.wxss # 页面样式文件 │ └── otherPage.js # 页面逻辑文件 ├── utils/ # 公共工具文件夹 │ ├── util.js # 公共工具文件 │ └── ... ├── node_modules/ # 第三方依赖库 ├── package.json # 包管理器配置文件 └── README.md # 说明文档 |
| 组件适配 | 编译时 | <View class="button-container"> <Button class="button" onClick={onClick}> {text} </Button> </View> | <view class="button-container"> <button class="button" bindtap="buttonClick">{{text}}</button> </view> |
| react语法-写法 | 编译时 | <View className="list"> {items.map((item) => ( <View key={item.id} className="list-item"> {item.title} </View> ))} </View> | <view class="list"> <block wx:for="{{items}}" wx:key="index"> <view class="list-item"> {{item.title}} </view> </block> </view> |
| react语法-运行 | 运行时 | state、props componentDidMount、componentDidUpdate、componentWillUnmount | data onReady、onHide、onUnload |
| api适配 | 运行时 | Taro调用 | wx?. window?. |

特点:

  • 重编译时,轻运行时:预编译部分代码减少启动时的编译时间,提升性能和用户体验 。
  • **编译后代码与 React 无关:**Taro 只是在开发时遵循了 React 的语法。
  • **直接使用 Babel 进行编译:**这也导致当前 Taro 在工程化和插件方面的羸弱。

弊端:

因为框架是自研的,就标志着taro需要考虑众多的边际条件,导致了构建系统的逻辑也变得繁杂了起来,出现了以下几个问题:

  • **维护困难:**每次需要新增一个功能,例如支持解析 Markdown 文件,就需要直接改动命令行,不够灵活
  • **难以共建:**命令行的代码非常复杂,而且逻辑分支众多,让很多想要一起共建的人难以入手
  • **可扩展性偏低:**自研的构建系统,设计之初没有考虑到后续的扩展性,导致开发者想要添加自定义的功能无从下手

Taro 2.0 的变化

Taro 2.0 的命令行变得非常轻量,只会做区分编译平台、处理不同平台编译入参等操作,随后再调用对应平台的 runner 编译器做代码编译操作,而原来大量的 AST 语法操作将会改造成 Webpack 处理

各个平台的runner任务:

  1. 代码转换:将源代码转换为特定平台的原生代码
  2. 构建:生成适用于目标平台的可执行文件或安装包
  3. 调试:提供调试工具,使开发者能够在目标设备上进行调试
  4. 打包:将所有资源(如图片、字体等)打包到最终的应用程序中
  5. 性能优化:通过分析和优化代码来提高应用程序的性能
复制代码
- **微信小程序**:将 JSX 编译成 WXML,编译 JavaScript 和 TypeScript 代码,CSS/SCSS/LESS 转换为 WXSS,图片等静态资源也会以特定的形式管理。

- **支付宝小程序**:编译结果类似于微信小程序,但是不同平台有其特定的模板和样式文件后缀名,比如支付宝小程序使用 .axml 作为模板文件后缀,.acss 作为样式文件后缀。

- **H5(Web 应用)**:生成经典的 HTML、CSS 和 JavaScript 文件,可以在各类现代浏览器中运行。

- **React Native**:编译生成能被 React Native 运行时理解的 JavaScript 代码和资源,保持代码逻辑与其他平台尽量一致,但针对原生应用的表现有一些差异化处理。

webpack主要工作:

  1. 模块打包:将多个JavaScript文件打包成一个或多个单独的文件,以便在浏览器中加载
  2. 代码分割:支持按需加载,即只加载当前需要的部分,而不是一次性加载整个应用程序,提高加载速度和用户体验
  3. 静态资源处理:其他类型的静态资源,如CSS、图片、字体等,对其进行压缩、合并等操作
  4. 插件机制:提供了丰富的插件系统,允许用户扩展其功能,比如添加额外的编译步骤、修改打包过程、生成代码分析报告等

优势:

  • 利于维护:大量的逻辑交由 Webpack 来处理,只需要维护一些插件
  • 更加稳定:相较于自研的构建系统,新的构建会更加稳定,降低一些奇怪错误的出现概率
  • 可扩展性强:可以通过自行加入 Webpack Loader 与 Plugin 的方式做自己想要的扩展
  • 各端编译统一:接入 Webpack 后,Taro 各端的编译配置可以实现非常大程度的统一

taro3.0开放式架构

前端的本质:调用了浏览器的那几个 BOM/DOM 的 API,如:createElementappendChildremoveChild等。

因此3.0创建了taro-runtime的包,然后在这个包中实现了一套高效、精简版的 DOM/BOM API(下面的 UML 图只是反映了几个主要的类的结构和关系)

然后通过 Webpack 的ProvidePlugin插件,注入到小程序的逻辑层。

这样,在小程序的运行时,就有了一套高效、精简版的 DOM/BOM API

新框架适配

在新架构加持下,Taro 不再仅局限于 React 阵营,可以不再限制使用的框架语法, Taro 官方内置了 React、Vue、Preact、Svelte、Nerv(京东凹凸实验室打造的类React前端框架) 五种框架的支持

开放式框架思想:

  • 插件开发者无需修改 Taro 核心库代码,即可编写出一个端平台插件
  • 插件使用者只需安装、配置端平台插件,即可把代码编译到指定平台
  • 开发者可以继承现有的端平台插件,然后对平台的适配逻辑进行自定义

横向扩展:扩展一个全新的编译平台;新的编译平台继承自TaroPlatforBase,如美团小程序

纵向扩展:继承已有端平台插件,扩展出新的编译平台;如 QQ 小程序插件继承于微信小程序插件。

优势:

  • 无 DSL 限制:无论是团队是 React 还是 Vue 技术栈甚至是其他,都能够使用 Taro 开发
  • 新特性无缝支持:由于新框架本质上是将各种框架运行在小程序上,因此,各种新特性也就无缝支持了
  • 社区贡献更简单:错误栈和 React/Vue 一致,团队只需要维护核心的 taro-runtime

Taro架构历程

taro4.x的展望

  • 支持更多的平台:可能增加对其他流行平台的支持,例如支持鸿蒙端平台
  • 性能提升:随着技术的进步,可以期待Taro 4.0在性能方面有显著的提升。这可能包括更快的编译速度、更高效的运行时环境
  • 社区贡献和开源生态:预计会有更多的开发者加入到Taro的开源社区中,并且会看到更多的第三方插件和组件库涌现出来
相关推荐
ZOMI酱4 分钟前
【AI系统】GPU 架构与 CUDA 关系
人工智能·架构
GISer_Jing5 小时前
React核心功能详解(一)
前端·react.js·前端框架
天天扭码7 小时前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
FØund4047 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
余生H7 小时前
transformer.js(三):底层架构及性能优化指南
javascript·深度学习·架构·transformer
凡人的AI工具箱7 小时前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
疯狂的沙粒8 小时前
如何在 React 项目中应用 TypeScript?应该注意那些点?结合实际项目示例及代码进行讲解!
react.js·typescript
运维&陈同学8 小时前
【zookeeper01】消息队列与微服务之zookeeper工作原理
运维·分布式·微服务·zookeeper·云原生·架构·消息队列