react native 升级0.64.2总结

一些基础变动参考官方文档:https://react-native-community.github.io/upgrade-helper/?from=0.60.5&to=0.64.2

1、native相关的修改

iOS

系统最低支持版本:9.0->10.0

在0.60的版本,一些基础库是通过手动一个个添加到podfile里引入的,现在官方提供了脚本,只需要调用这个脚本就行了

use_react_native!(
   :path => '../rn-pack/node_modules/react-native',
   :hermes_enabled => false
)

podfile的其余修改内容见头部链接。这里有点不同的是官方是通过use_native_modules获取的path,因为我们的项目结构与官方建议的不同,所以不能直接使用这个方法,这边我是直接指定的相对目录。

android

现行框架使用的集成方式为aar集成react-native,且依赖取自内网nexus仓库的maven-3rd-releases库,需要在本地上传0.64.2版本的react-native包。

之前没有留存这方面的更新文档,而且框架的集成方式和官方文档差距很大,导致有点坑需要填。

首先就是直接更新版本后无法下载依赖,原因是react-native依赖需要先手动上传新版本到maven-3rd-releases库。

其次是react-native依赖的包如何生成已经没有人知道,网上没有相关资料,花了些时间研究了一下RN的项目运行逻辑,react-native.aar包应由node_modules/react-native/ReactAndroid项目生成,定位了生成的aar包具体位置应为node_modules/react-native/android文件夹下。

再然后发现rn-pack项目中并没有node_modules/react-native/android文件夹,并且node_modules/react-native/ReactAndroid项目缺少关键依赖并不能顺利运行,头秃。

最后新建了一个标准的RN项目,在node_modules/react-native/android文件夹中找到了一个localMaven仓库,里面存在需要的react-native-0.64.2.aar包。

image2021-9-1_17-15-34

这时候需要将localMaven仓库上传到内网nexus仓库的maven-3rd-releases库,又遇到了一个没见过的问题,本来想在发布到localMaven的地方改一下仓库地址,结果标准RN项目的ReactAndroid项目也无法运行,只能考虑直接上传文件。

使用android-mvn-releaser账号登录内网nexus仓库并没有网络图片上的上传文件按钮,可能是权限限制了,只能考虑命令行本地上传:

mvn deploy:deploy-file -DgroupId=com.facebook.react -DartifactId=react-native -Dversion=0.64.2 -Dpackaging=aar -Dfile=react-native-0.64.2.aar -Djavadoc=react-native-0.64.2-javadoc.jar -Dsources=react-native-0.64.2-sources.jar -DpomFile=react-native-0.64.2.pom -Durl=http://nexus.xxx.com/repository/maven-3rd-releases/ -DrepositoryId=maven-3rd-releases

2、部分三方库更新(仅供参考)

  1. @react-native-community/viewpager废弃,使用react-native-pager-view

  2. ART从react-native里分离,使用@react-native-community/art

  3. react-native-webp-support废弃,替换成react-native-webp-format (iOS only)

  4. 一些库的版本升级:

    • @react-native-community/cameraroll
    • react-native-fast-image (iOS only)
    • react-native-fs
    • react-native-modalbox
    • react-native-webview

3、升级时遇到的一些问题

iOS项目运行时报错:Error: Cannot find module 'react-native-codegen/package.json'

报错点位于generate-specs.sh脚本,将其替换为最新的版本可以正常运行,但是0.64.2版本的rn使用的还是老版本的脚本,所以我们只能自己修改了。

修改后有两种处理方法

1、push到自己的仓库中,package.json直接指定仓库地址,使用修改后的版本。

2、使用patch-package库,可以保存对于三方库的修改。

参考https://github.com/pnpm/pnpm/issues/3325

ScrollView中嵌套使用VirtualizedList会报error,但是不影响使用

由于我们使用的瀑布流组件是通过这种方式实现的,目前大部分的实现也是通过这种方式,暂时没找到很好的解决方法。

Android项目运行时报错

1、java.lang.NoSuchMethodError: No interface method putArray(Ljava/lang/String;Lcom/facebook/react/bridge/WritableArray;)V in class Lcom/facebook/react/bridge/WritableMap; or its super classes 2、java.lang.NoSuchMethodError: No interface method putMap(Ljava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V in class Lcom/facebook/react/bridge/WritableMap; or its super classes 3、java.lang.NoSuchMethodError: No interface method pushArray(Lcom/facebook/react/bridge/WritableArray;)V in class Lcom/facebook/react/bridge/WritableArray; or its super classes 4、java.lang.NoSuchMethodError: No interface method pushMap(Lcom/facebook/react/bridge/WritableMap;)V in class Lcom/facebook/react/bridge/WritableArray; or its super classes

以上四个报错都是一个类型,WritableMap和WritableArray无法自动转换为对应的父类ReadableMap和ReadableArray,原因不明。

报错的来源都是第三方库的原生代码,将其重新编译打包后问题消失,应该是旧的aar包中依赖的RN版本不是最新版本导致。

Android项目出现闪退

查看报错日志,显示EventDispatcher是一个interface,但在编译过的包中是一个class,报错来源是RN的手势库react-native-gesture-handler。

原因是在原来的0.60.5版本RN中,EventDispatcher是一个class,在升级后的0.64.2版本RN中,EventDispatcher是一个interface。手势库react-native-gesture-handler编译出来的aar包中,依赖的是0.60.5版本RN。由于项目中对RN的各个依赖三方库是通过编译后的aar包进行依赖,升级RN后没有重新对react-native-gesture-handler库进行打包,导致旧的aar包运行崩溃。

解决办法很简单,只需要重新对react-native-gesture-handler库进行打包,另外排查了其他RN三方库,发现react-native-svg库也使用了EventDispatcher,应该也会有一样的问题,也需一起重新打包。

为避免出现其他问题,对所有第三方RN库都进行重新编译打包。另外可以考虑将各个三方库使用module源码依赖的方式引入,这样的话就不会出现这种RN升级后需要重新编译打包的问题了。

4、其他

版本更新之后,@types版本也需要一起更新,部分规则更加严格,需要按照lint结果进行修改。

知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
comments powered by Disqus