两个月前,我们发布了 Taro v3.6 的 canary 版本,在技术委员会和社区范围内提供跨端路由库、跨框架组件等主要能力和重要修复的测试,并发起社区投票正式确定了当前版本的代号 —— Reach。
日前 Taro v3.6 正式版本已经发布,下文将围绕 3.6 版本内的跨端、平台能力支持等多个方面展开,快速了解在 v3.6 中各个重要特性。
一、跨端能力支持
支持各类跨端能力,抹平多端研发之间的体验差异,是 Taro 一直以来尝试去实现的,基于 Taro 3 适配多端前端 UI 框架的逻辑,通过在小程序端模拟实现框架所需的 BOM / DOM API 就能达成对于各类跨端能力的适配。
1. 支持路由库
在 Web BOM 中,History & Location 对象是重要组成部分,它们是实现前端路由的关键。Taro 为支持前端路由库的使用,在运行时中引入了 histroy
location
对象的实现,同时尽可能与 Web 端规范对齐。通过在 window
对象上访问到 history
和 location
对象,并支持监听 hashchange
和 popstate
事件,为跨端使用路由库提供基础。
// 统称: 页面路由状态
window.history
window.location
// 支持监听事件
window.addEventListener('hashchange', () => {})
window.addEventListener('popstate', () => {})
小程序天然支持多页面(pages
数组配置),因此 Taro 并非以整个应用为一个路由系统,而是顺应小程序规范以页面维度进行路由管理。每当切换页面时,会将当前页面的页面路由状态缓存。跳转至新页面后会重新创建页面路由状态,并挂载在 window
对象上。当返回上一级页面时,会将上一级页面的页面路由状态重新挂载到 window
对象中。
至此,可以在小程序中使用成熟的前端路由库了,包括 react-router
和 vue-router
。在路由库中,诸如 <Link>
组件内部会动态生成 <a>
标签,因此需要引入 @tarojs/plugin-html
插件以支持在 Taro 中使用 html
标签开发组件。
{
"plugins": ["@tarojs/plugin-html"]
}
在 Taro 编译过程中,当 DOM 序列化数据的 nn 字段为 HTML 标签时,标签会映射为对应的小程序组件名称。由于无法提前预知动态标签,因此需要应用显式告知可能会使用到的动态标签。例如在应用中塞入一个无样式的标签名即可:
<View>
<a></a>
</View>
更多细节可以查看 官方文档,也可以查看官方提供的 DEMO 获知更多用法。
2. 支持网络请求库
与适配各路由库类似,通过对运行时补充就能支持绝大多数的网络请求库,所有请求库在底层都是通过使用 XMLHttpRequest 或 Fetch 提供能力支持的,而请求库大多都兼容 XMLHttpRequest
对象,也即是在提供 XMLHttpRequest
对象实现的基础上,就能支持绝大多数的第三方库。
支持这些成熟的网络请求库(例如 axios 等)就能为开发者在跨端研发场景下,提供更好的研发体验。通过引入 @tarojs/plugin-http 插件,为小程序环境提供网络请求库所需的运行时环境支持。
{
"plugins": ["@tarojs/plugin-http"]
}
注意:当前 @tarojs/runtime 在小程序环境中缺少
Blob
、FormData
、File
对象,这在网络请求库的文件上传特性中是必须的,故暂不支持。
在支持网络请求库的同时,考虑到部分用户,特别是 web 转小程序的项目中依赖 cookie
实现鉴权,@tarojs/plugin-http 插件模拟实现了 document.cookie
api 以及通过 http 响应头 Set-Cookie
来设置客户端 cookie
值 ,行为和 web 中保持一致。 此功能默认设置为关闭,需要的可通过 enableCookie
配置开启。
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
enableCookie | Boolean | false | 支持 document.cookie 、 通过后端返回 Set-Cookie 响应头来设置 cookie |
disabledFormData | Boolean | true | 是否禁用 FormData 全局对象 |
disabledBlob | Boolean | true | 是否禁用 Blob 全局对象 |
在 @tarojs/plugin-http 插件中,以 axios
作为基准库完成测试,如果在使用其他请求库时遇到适配问题,可在社区或通过 issues 反馈相关信息。
二、平台能力支持
拓展更多端平台,适配支持各端能力与特性,是跨端解决方案不断发展的重要组成部分之一。
1. 支持鸿蒙端平台插件
在 Taro 与 OpenHarmony 建立官方合作关系,并受邀成立 CrossPlatformUI Sig(跨平台前端框架兴趣小组)后,让 Taro 支持支配鸿蒙就一直在议程上,鸿蒙的方舟开发框架提供类 Web 范式编程,支持使用 JS 开发 UI 层,其语法与小程序相接近,可以沿用 Taro 现有的架构适配鸿蒙。
持续关注 Taro 的开发者可能还记得,在 v3.5-canary 版本时,我们曾推出支持 Taro 应用适配到鸿蒙平台的插件,但最终没有合入 v3.5 版本主干并顺势推出该能力。
在 @tarojs/plugin-platform-harmony
端平台插件经过一段时间的打磨,相关能力与特性也在社区推进下持续优化,框架编译的项目在鸿蒙开发板上得到进一步验证,同时在 Taro v3.5 新增的 @tarojs/webpack5-runner
编译内核也能够为鸿蒙项目编译提供支持,终于我们在 v3.6 中再次为社区开发者提供了适配鸿蒙的端平台插件。
// config/index.js
config = {
// 配置使用插件
plugins: ['@tarojs/plugin-platform-harmony'],
// harmony 相关配置
harmony: {
// 【必填】鸿蒙应用的绝对路径
projectPath: path.resolve(process.cwd(), '../MyApplication'),
// 【可选】HAP 的名称,默认为 'entry'
hapName: 'entry',
// 【可选】JS FA 的名称,默认为 'default'
jsFAName: 'default'
}
}
具体使用方法可查看官方文档,需要注意鸿蒙插件不在 Taro 项目内维护,所以并不会每次发布同版本号版本,直接使用 minor 与 Taro 版本号相同的版本即可。
特别感谢以下同学为鸿蒙适配作出的贡献:
@AdvancedCat、@jiaozitang、@huozhongyi123、@troy-sxj、@JSZabc、@crazyonebyone、@evernoteHW、@soulhat、@xueshuai、@LuMeiling
2. React Native 能力
为了让整体开发体验跟 RN 更加一致,减少开发者的理解成本。我们对 @tarojs/rn-runner 的代码进行了重构。将 Taro RN 需要的所有编译逻辑,都封装到了 metro 配置中,与 RN 项目集成会更加灵活。
新版本在项目根目录下会创建入口文件 index.js 和配置文件 metro.config.js。如项目本身有这两个文件,则不会生成,需要参考模板进行添加或合并。另外 Taro RN 的相关配置,集中在 resolver 和 transformer 中,可根据相关源码自行覆盖调整。
React Native 0.70 版本已于 2022-9-5 正式发布,在 0.70 版本中 Hermes 已成为默认的 JS 引擎,
v3.6 版本将与 RN 默认配置保持一致,如不需要可自行关闭。Hermes 也带来了 RN 性能的较大提升,特别是启动场景,详细内容参考官方文章。
Taro 将与 RN 社区保持同步,将默认的 RN 版本设置为 0.70。相关依赖也已同步至最新版本,仍然可使用 yarn upgradePeerdeps
进行更新。@react-native-community/clipboard
及 @react-native-community/cameraroll
已被弃用,旧版本升级后需要删除。
注意:升级后将不再支持 iOS 12,详细内容请参考 discussions。同时 Taro Playground 作为 RN 端的调试工具及跨端 Demo 同步更新至 v3.6。
3. Web 端能力
通过在社区中收集的相关问题反馈,Taro Web 各类特性也一直在不断推进,让开发者在多端研发的体验能够尽可能达成一致。面对各类自定义 Web 端能力的需求,虽然有很多方案可以提供组件、API 等能力的补充,但类似小程序端平台插件这样的能力在 Web 端中并没有得到支持。
在 3.6 版本中,我们将 Web 端各类定制化的能力从 runner 中转移到 @tarojs/plugin-platform-h5
插件中提供,譬如通过配置 useHtmlComponents
模式替换使用的组件库;注册 Web Components 组件库,配置各前端 UI 框架组件适配器;移除不必要的 API 等等特性。
class H5 extends TaroPlatformWeb {
// ...
}
export default (ctx) => {
ctx.registerPlatform({
name: 'h5',
useConfigName: 'h5',
async fn({ config }) {
const program = new H5(ctx, config)
await program.start()
},
})
}
和小程序端一样,借助于插件或 TaroPlatformWeb
基类,开发者可以很容易横向或纵向拓展 Web 端的各项能力,详情可参考文档。
Web 端也一直在补充各类开发者常用的组件与 API 抹平与小程序端的差异。在 v3.6 版本中新增生命周期、WXML 相关的 API 支持若干,例如:createIntersectionObserver
、createMediaQueryObserver
等,同时新增 movable-area
、movable-view
等组件支持。
在社区开发者交流时,我们也发现了部分研发场景下需要监听各 API、组件不支持事件,相比于支持 canIUse 方法在跨端转换场景中能够更有效定位问题,所以通过支持 __taroNotSupport
事件满足相关需求,可以参考以下示例使用。
interface IOption {
name: string // 不支持的组件或 API 名称
type: 'method' | 'component' // 'method': API; 'component': 组件
category: 'permanently' | 'temporarily' | 'weixin_corp' // 'weixin_corp': 仅在微信公众号 JS-SDK 环境下支持
args?: any[] // API 传入参数
instance?: unknown // 组件实例
}
Taro.eventCenter.on('__taroNotSupport', (option: IOption) => {
console.warn('调用不支持的 API 或组件', option)
})
三、跨框架组件库
借助于 stencil,Taro 3 得以通过 Web Components 实现一套跨框架组件库,通过适配器将 Taro 的组件库提供给各个前端 UI 框架使用,开发者也可以基于这些封装上层组件,提供更多有趣的能力。
1. Web 端适配器
出于降低开发者维护门槛,与 stencil 组件库打包流程更好兼容等多方面考虑,在 3.6 版本中我们在升级 stencil 依赖版本的同时,通过官方提供的 ds-output-target 工具替换了原有的自定义适配器。
该版本适配器更好的抹平各个框架组件使用差异,补齐过往版本迭代过程中部分特性兼容性的缺失问题,为开发者提供更好的体验。在 3.6 中依旧保留过往版本各框架适配器,可以参考以下示例通过配置别名替换组件库适配器(不建议使用,后续不会维护旧版适配器,可能无法得到新的组件或特性支持)。
// config/index.js
const config = {
h5: {
webpackChain(chain) {
chain.resolve.alias.set(
// 当前版本适配层地址 @tarojs/components/dist/[framework]
'@tarojs/components/dist/react',
// 旧版本适配层地址 @tarojs/components/dist/[framework]/component-lib
'@tarojs/components/dist/react/component-lib'
)
},
},
}
2. 虚拟列表
作为从 Taro 3 开始支持的上层组件,虚拟列表应当是很多开发者都熟悉的特性,在过往版本中也有过数次升级,支持包括 unlimitedSize、relative 定位模式等特性,在 v3.6 版本中我们再次对虚拟列表做出了调整,将其从 @tarojs/components
包中抽离到 @tarojs/components-advanced 中维护(4.x 版本之前开发者依旧可以通过 @tarojs/components/virtual-list 引用虚拟列表组件),也欢迎大家一同参与上层组件库的维护与共建,沉淀更多跨端可用的能力。
在新版本中,虚拟列表支持在选择 preact、vue3 框架构建的项目中使用,同时在使用各个前端 UI 框架的项目中都支持使用选择 absolute
****、****relative
********不同定位方式,unlimitedSize 模式与传入 itemSize 函数等特性也得到支持。
以 Vue 为例,我们需要在入口文件声明使用:
// app.js 入口文件
import Vue from 'vue'
import registerVirtualList from '@tarojs/components-advanced/dist/components/virtual-list'
// Note: 使用以下路径导出插件可以在 vue 中获得更好的类型支持
// import registerVirtualList from '@tarojs/components-advanced/dist/components/virtual-list/vue'
Vue.use(registerVirtualList)
一个最简单的长列表组件会像这样,virtual-list
的 5 个属性都是必填项:
<! –– row.vue 单项组件 ––>
<template>
<view :id="id" :class="index % 2 ? 'ListItemOdd' : 'ListItemEven'"> Row {{ index }} : {{ data[index] }} </view>
</template>
<script>
export default {
props: ['id', 'index', 'data'],
}
</script>
<! –– page.vue 页面组件 ––>
<template>
<virtual-list
wclass="List"
:height="500"
:item-data="list"
:item-count="list.length"
:item-size="100"
:item="Row"
width="100%"
>
<! –– Vue 中支持列表首尾使用的插槽,对应 React 中的 renderTop、renderBottom 参数 ––>
<template v-slot:top>
<view>top</view>
</template>
<template v-slot:bottom>
<view>bottom</view>
</template>
</virtual-list>
</template>
<script>
import { markRaw } from 'vue'
import Row from './row.vue'
function buildData(offset = 0) {
return Array(100)
.fill(0)
.map((_, i) => i + offset)
}
export default {
data() {
return {
Row: markRaw(Row),
list: buildData(0),
}
},
}
</script>
需要注意的是,为抹平多框架参数差异便于维护,旧版本中部分命名会统一修改,比如在 React 版本中通过 children 传入的子节点组件改为 item;Vue 中的 wclass、wstyle 这类写法也不再支持。
在新版本中,根据需求和研发场景合理设置 itemSize
、overscanCount
、placeholderCount
等参数优化长列表,可以获得比旧版本更加顺滑的体验,更多详情可以参考官方文档。
四、研发生态
1. 小程序持续集成 CI
去年 Taro 提供小程序持续集成插件 @tarojs/plugin-mini-ci
,帮助开发者提供更好的研发体验,经过一年的项目沉淀和反馈,在本次版本重构了去年的所有代码,并提供了更优秀体验和灵活的配置。
- 本次新增特性支持独立的
open
、preview
、upload
命令,操作自定义目录适用于将 taro 作为项目一部分(混合开发)的开发场景; - 同步更新各个小程序端的 CI API 变更(阿里系、抖音小程序变化最大)
- 新增钉钉小程序 CI 集成;
- 新增京东小程序 CI 集成;
- 统一所有平台 CI 构建后的输出数据,并将数据传递给新增的
onPreviewComplete
、onUploadComplete
两个钩子用户可以编写新的插件,基于这个钩子实现 飞书、钉钉 的 CI 推送功能等等。
以下为当前各平台支持的功能情况表:
平台/功能 | 自动打开 IDE | 输出预览二维码 | 输出体验二维码 |
---|---|---|---|
weapp | ✅ | ✅ | ✅ |
qywx | ✅ | ✅ | ✅ |
alipay | ✅ | ✅ | ✅ |
dd | ✅ | ✅ | ❌ |
swan | ✅ | ✅ | ✅ |
jd | ✅ | ✅ | ✅ |
ps: 该插件在 taro3.6.0 版本以下亦可支持单独使用,插件版本号无需保持与其他包同步。
更多详情可以参考官方文档,同时要特别感谢 @bigMeow 为 CI 自动化脚本做出的贡献~
2. PostCSS 版本升级
在 Taro 项目持续迭代的过程中,部分依赖稳定没有实时跟进各个社区内的特性与优化,并升级相关依赖,PostCSS 就是其中之一。如果开发者想要通过新版本的特性来优化构建流程与最终产物,相对会很困难且可能会存在一定问题阻塞。
为此在 3.6 canary 通过梳理项目内相关插件与依赖,对 PostcCSS 版本进行梳理并升级,升级后版本为 v8.4.18。本次升级主要包含以下内容:
- 对 Taro 内部的 PostCSS 插件使用 PostCSS 8 版本 API 进行改写,降低代码量同时减少插件对 CSS 扫描次数进而提高构建速度;
- 使用 peerDependencies 管理 postCSS 依赖,降低用户的 node_modules 体积和复杂度;
- 对 Taro 全量模板的 PostCSS 版本同步进行更新,方便开发者对新特性的使用。
特别感谢 @xueshuai 为相关工作做出的贡献,希望开发者可以因此获得更好的研发体验。
3. 类型与文档自动同步
快速同步各平台支持的类型,一直以来都是十分头疼的问题之一,想要实时跟进各个平台以提升用户体验十分困难,更多时候我们都通过开发者提交的 PR 或 issue 对这些平台的类型更新维护。如果能够根据各个小程序平台官方提供的文档自动化生成类型,这对于框架维护和开发者来说会是一个很棒的体验。
通过在 Taro 社区中的积极探讨和论证,我们引入了自动同步各小程序平台组件类型的脚本机制,并通过与 GitHub CI 让机器人为 Taro 仓库提交类型更新 PR。组件类型的自动化同时让 Taro 的文档在类型更新时,同步这些平台组件的变更,为开发者提供更好的文档索引能力。同时我们也在文档提供了 canIUse 页面,供开发者快速检索组件、特性在各个平台支持的程度。
希望后续也能够通过和各平台合作的方式优化该能力,为开发者提供更好的体验。在这里特别感谢 @rebinv8 为组件类型自动化脚本做出的贡献~
4. Taro Playground 同步升级
作为 RN 端的调试工具及跨端 Demo,Taro Playground 同步更新 v3.6 更新。此次更新无法保证向下兼容,使用旧版本 Taro 的开发者,如需调试 Android,可在 releases 中下载旧包进行调试。在 App Store 中,我们只上架最新版本,需要旧版本的开发者请不要开启应用自动更新。如不慎升级,需自行打包编译,或联系我们加入测试组。
五、升级指南
1. 创建 v3.6 版本项目:
# 安装 v3.6.0 的 CLI 工具
npm i -g @tarojs/cli@latest
# 创建项目
taro init taro_project
# 也可以跳过安装 CLI 工具使用 npx 创建项目
npx @tarojs/cli@latest init taro_project
2. 已有项目升级到最新版本:
- 将 package.json 文件中 Taro 相关依赖修改为
3.6.0
版本; - Taro v3.6 将 web 端插件化,需要新增依赖
@tarojs/plugin-platform-h5
,同时@tarojs/router
、@tarojs/taro-h5
不再需要额外声明依赖,可自行移除; - 重新安装依赖,如果安装失败或打开项目失败,可以删除
node_modules
、yarn.lock
、package-lock.json
后重新安装依赖重新尝试。
最后
自 Taro 引入技术委员会等机制后,与社区互动愈加频繁,Taro 也得益于诸多贡献者的帮助有能力去实现更多有意思的特性,给开发者带来更好的用户体验,这也是 Taro v3.6 在代号「Reach」中的期待。感谢各位参与到 Taro 开源生态共建的同学们,所有的努力都让 Taro 的生态更加美好,为建立更加完善、更加可持续的 Taro 开源生态,贡献力量!