跨端实践 | Taro 版本从 v3.3.x 升级到 v3.5.x 的踩坑指南

2,133 阅读10分钟

本文是将 Taro v3.3.12 升级到 Taro v3.5.6 的项目实战,基于 Vue 2 的框架,采用 webpack5 编译器,node 版本 v16.12.0。

前言

Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发小程序等应用。

在 2019 年, Taro 框架的发展初期(1.x 版本),我们团队就已经开始接触,并成功落地了多个大型项目。后续,Taro 团队先后发布了 2.x、3.x 版本,我们也是同步进行了多个版本的迭代跟进。目前,团队落地项目中的 Taro 版本,基本稳定在 v3.3.12。所以,对于 Taro 框架的项目实践,我们已经具备了相当丰富的经验。

前一阵子,Taro 官方团队宣布了 Taro v3.5 版本正式发布,经过初步实践,我们很惊喜的发现在 v3.3.12 版本中困扰已久的很多问题,都被成功修复了。经过团队内部多次激烈讨论之后,我们决定将项目中的 Taro 版本从 v3.3.12 统一升级到 v3.5.6。

考虑到 v3.4 和 v3.5 这两个版本都存在框架层面的颠覆性改动,势必会带来一些难以预料的改动点(官方文档未声明),所以本文主要记录 Taro 版本升级实践过程中所遇到的一些问题,以及临时的解决方案。

版本差异梳理

考虑到目前团队项目的应用场景,主要为微信小程序和 H5 端项目实践,所以这里主要对比了这两个端的差异点,其他端的内容可以根据需要,自己查看 Taro 的官方发布说明。下图是从 Taro v3.3.12 到 v3.5.6 的各个版本的主要差异点和注意点(个别无重点的版本被省略),仅代表我的个人观点:

版本号更新说明备注
3.3.14为 Taro.getEnv() 增加快手小程序环境变量
3.3.15H5:
1、修复浏览器多级后退造成的错误。
2、支持使用相对路径地址跳转到新页面。
3、修复快速切换 TabBar 时,页面展示错误的问题。
3.3.17小程序:
1、优化对 vant weapp 的兼容。
2、修复 Vue3 首次进入页面会触发两次 onShow 的问题。
3.3.18H5:
1、新增自定义配置多路由能力。
小程序:
1、修复阿里小程序 2.0 构建报错。
3.4.01、支持使用 Preact。
2、支持 Composition API 版本的小程序生命周期钩子。
3、新增 defineAppConfig 与 definePageConfig 编译宏。
1、旧项目升级到 Taro v3.4 需要安装对应的框架适配插件。
2、百度小程序使用 onInit 代替 onLoad 生命周期,以优化首次启动时间。
3、H5 端调整 showModal 返回的 errMsg 参数,和小程序对齐。
3.4.2小程序:
1、修复 preact 小程序生命周期不触发的问题
2、修复编译小程序插件时不能使用 plugin-html 的问题。
3.4.3支持微信小程序 Button 组件的 open-type 属性以获取头像昵称。
小程序:
1、增加 Taro.getTabBar API 。
2、修复独立分包中事件不触发的问题。
H5:
1、tabbar 适配 iPhoneX 及以上全面屏。
3.4.4小程序:
1、修复小程序插件无法使用 Taro hooks 的问题。
2、修复使用 @tarojs/plugin-html 时引入的 HTML 样式权重问题。
3.4.5sass 依赖的版本统一升级到 v1.50.0
3.4.6小程序:
1、支持 onUnload 生命周期。
2、修复在 Taro 编译配置文件中获取不到 process.env.TARO_ENV 变量的问题
3.4.8小程序:
1、支持微信小程序 Input 组件的安全键盘属性。
3.4.9H5:
1、修复跳转进入到可下拉刷新页面,但无法下拉刷新的问题。
3.4.11H5:
1、支持 onAppShow、onAppHide、offAppShow、offAppHide 方法。
3.5.01、编译提速,使用 webpack5 编译
2、提供了 pnpm 包管理工具使用选项
使用 webpack5 编译时,开发者需要先卸载 @tarojs/mini-runner 和 @tarojs/webpack-runner,然后安装 @tarojs/webpack5-runner
3.5.2H5:
1、prebundle 默认继承 webpack 配置,并支持开发者自定义拓展。
小程序:
1、优化主入口引用样式文件编译问题。
3.5.5H5:
1、修复 textarea 组件高度设置无法生效的问题。
3.5.6小程序:
1、修复 webpack5 预编译导致的报错问题。
H5:
1、修复 input 组件 type=number maxlength=-1 时,内容无法输入问题。
2、修复 input 组件 type 为 number 或 digit 时,输入特殊符号导致交互异常的问题。
3、修复 onShow 和 onReachBottom 事件多次触发的问题。
3.5.7小程序:
1、修复 App 没有触发首次 componentDidShow 系列生命周期的问题
H5:
1、修复 onLaunch 参数的数据结构与小程序的不一致的问题
2、修复 request API 与小程序的网络请求处理不一致的问题
3.5.8H5:
1、修复 Button 组件 disabled 参数失效问题
经过验证,并未修复 disabled 问题
3.5.9小程序:
1、支持 onUnhandledRejection 生命周期
经过验证,当前版本 H5 端白屏,不可用
3.5.10修复配置文件读取报错的问题经过验证,当前版本 H5 端白屏,不可用

问:为什么不直接升级到 Taro 最新版本? 答:1、准备升级时,Taro 的最新版本仅为 v3.5.10。 2、我们主要关注的功能点在 v3.5.6 版本已经提交 PR 合入。 3、v3.5.7 和 v3.5.8 的主要修复点,经过验证,发现并没有完全修复。同时,v3.5.9 引入了新问题,导致 v3.5.9 和 v3.5.10 这两个版本的 H5 端完全不可用。

升级需要调整的代码

依赖变更

1、package.json 文件中的 @tarojs/xxx 依赖,从 3.3.12 修改为 3.5.6。

2、新增 @tarojs/plugin-framework-vue2 依赖,因为从 v3.4 版本开始,各前端框架的适配逻辑被拆分到了对应的插件中,因此旧项目升级时需要安装对应框架的适配插件(如:@tarojs/plugin-framework-react@tarojs/plugin-framework-vue2@tarojs/plugin-framework-vue3)。

3、新增微信小程序平台编译插件 @tarojs/plugin-platform-weapp,在 v 3.3.12 版本中,微信小程序平台编译插件是集成在框架内部的,而在 v3.5.6 中,需要用到哪一个平台编译,就单独引入哪一个插件即可。

4、新增@tarojs/helper@tarojs/router@tarojs/shared@tarojs/taro-h5@vue/babel-preset-jsx这些依赖。因为从 v3.5 开始,Taro 项目支持使用 pnpm 包管理工具,而在 pnpm 中是不允许存在幽灵依赖的,需要开发者手动安装。

5、webpack 编译器模块依赖变更,可由原来的 @tarojs/mini-runner+@tarojs/webpack-runner 修改为 @tarojs/webpack5-runner。因为从 v3.5 开始,Taro 支持使用 webpack5 编译,并重写了编译器模块。

6、webpack 依赖版本修改为 "^5.73.0"

7、全局 @tarojs/cli 版本更新为 3.5.6,可执行命令npm i @tarojs/cli@3.5.6 -g 进行升级。但如果只是升级单个项目的话,建议在当前项目本地安装 npm i @tarojs/cli@3.5.6 -D,然后通过 package.json 中的 scripts 去启动项目。

配置变更

1、config/index.js 文件中的 compiler 编译器字段改为 "webpack5"。

/** config/index.js */
const config = {
  // 自定义编译工具,可选 'Webpack4' 或 'Webpack5'
  compiler: "webpack4" || "webpack5",
};

2、可选择性的开启持久化缓存功能,添加 cache 字段。

/** config/index.js */
const config = {
  cache: {
    enable: false, // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
  },
};

3、prebundle 配置在 v3.5.6 中开发环境默认是开启状态,如果开发者不清楚实际作用的话,建议主动关闭。

/** config/index.js */
const config = {
  compiler: {
    type: "webpack5",
    prebundle: {
      enable: false,
    },
  },
};

项目代码变更

1、从 v3.3.12 升级到 v3.5.6 之后,我们在展示层能最直观的看到 H5 端的页面布局样式完全乱了(字体变大,布局错乱等)。究其原因,Taro 从 v3.5 开始,页面的 px 单位换算规则有细微调整,由下面两个图对比可知。

虽然,Taro 框架在底层已经做了各种逻辑适配,但如果旧版本项目中,仍然存在着部分未兼容到的写法,则会出现所说的字号变大,页面布局混乱的现象。

针对这个问题,最好的方式肯定是排查一下项目中样式混乱的模块,优化一下代码逻辑,不外乎就是调整一下样式代码。不过,也有一种临时救急的方案,我们可以主动将 Taro v3.5.6 中尺寸换算规则调整到与 v3.3.12 一致。示例如下:

/** config/index.js */
const config = {
  designWidth: 750,
  deviceRatio: {
    640: 2.34 / 2,
    750: process.env.TARO_ENV === "h5" ? 640 / 750 : 1, // 目前发现只有 H5 端存在这个问题,将 1 改为 640/750
    828: 1.81 / 2,
  },
};

2、升级前后的 css Modules 表现不一致,上面有提到升级之后页面的布局样式完全混乱,其实有一部分原因是由 css Modules 造成的。

在 Taro v3.3.12 时,页面中的 style 标签上定义了 module 标记,但没有使用,其表现为全局样式的形式,不会有自定义编译。但在 Taro v3.5.6 时,如果你定义了 <style lang="less" module> ,但页面中的 class 没有通过 $style.xxx的形式来使用,则页面中样式都会解析不到。

针对此类问题,最好的方式也肯定是在代码层面,进行相对应的修改,module 形式就用自定义转换的调用方式,global 就用全局样式的定义方式。不过,也有一种临时救急的方案,如果在旧项目中就没有使用 cssModules 能力的话,我们可以全局去掉 module字段,或者我们给所有的模块都添加 :global{这里是原来的样式定义} 作用域包含,将其定义为全局。

如果现在还不太清楚 css Modules 的正确使用方式,可以参考如下:

<template>
  <!-- 未定义 module 名,则可直接通过 $style 调用 -->
  <p :class="$style.red">
    This should be red
  </p>
  <p class="bold">
    This should be bold
  </p>
</template>

<style module>
.red {
  color: red;
}

/* 定义全局作用域 */
:global {
  .bold {
    font-weight: bold;
  }
}
</style>

升级带来的好处

编译速度提升

首先,编译速度得到较大提升,引用 Taro 官方团队发布的一张性能对比图(基于 NutUI 组件示例库)如下:

图片来自Taro官网

图片来自Taro官网 (图片来自 Taro 官网)

同时,我也挑了几个比较复杂的业务项目,进行了升级前后的编译速度对比。可能是业务项目和 NutUI 组件库的项目性质不同,或者是项目配置上没有做好,对于首次的编译速度,升级前后并没有多大的提升,甚至多了一点耗时,升级前基本稳定在 60s 左右,升级后基本稳定在 65s 左右(仅供参考,也有可能是电脑环境因素干扰等等)。

但是升级到 webpack5 之后,我们就可以选择开启持久化缓存功能,一旦开启,编译速度能够直接提升到 20s 左右,这简直就是质的飞跃了。不过这里要特别注意,持久化缓存必然会带来内容未更新的开发风险,开发者还需要谨慎使用。

Taro 遵循 Webpack “编译安全比编译速度重要” 的理念,默认不开启持久化缓存。当开发者设计好缓存策略后,强烈建议开启持久化缓存。

新特性

对于框架升级的考量,编译速度的提升只是其中一小部分,我们更关注的其实是通过升级,是否能够解决目前版本无法解决的问题。在前文的版本差异性对比中,我们也可以看到有很多的点,仅仅通过业务侧的限制或者组件封装,是难以达到较好的用户体验的。

我们这次框架升级,主要就是来解决如下几个问题:input 输入框交互异常问题、tabbar 快速切换页面显示错误问题、部分小程序生命周期异常问题。

框架的升级会增加新的功能特性和一些新的语法糖或接口方法,也修复了遗留的问题。但同时,也可能会引入一些新的问题,这个时候则需要架构师从更多的层面来考虑本次的升级是否合理。

最后

本次的 Taro 版本升级实践,虽然遇到了一些问题,但也给我们带来了非常多的启发。我们不仅要关注框架升级能否解决技术上的遗留问题,也要关注框架升级所带来的风险。因为跨版本升级,存在着大量的代码逻辑修改,开发人员无法对升级的影响点完全掌控。所以一定要安排足够的测试资源,准确地做到全量回归测试。

参考资料