升级思路
因为项目自定义比较多,不适合用各类升级工具,主要参考upgrade helper提供的改动点。
遇到问题
缓存问题
缓存问题无疑是遇到最多的,这里也就不多说,无非就是清lock/删node_module/清pod/rebuild...
Installation problem zlib: unexpected end of file
解决:
npm cache clean --force
重装pod
,发现首次安装特别慢
发现clone https://github.com/CocoaPods/Specs
特别慢,看了代码就会发现这个项目文件特别多,慢是肯定的。
解决:下载到本地,在本地做替换,注意.git
文件。
具体可以看https://www.jianshu.com/p/73ba4ee54b72
pod libwebp
始终不成功
libwebp
下载的源是https://chromium.googlesource.com/webm/libwebp/,这个地址即便你全局翻墙也下不下来
解决方案:替换成github上的镜像源。
具体可以看https://www.jianshu.com/p/9e3eec3d8fe0
安卓gradle
编译问题
build failed with: Could not find method enabled() for arguments [[]] on task ':app:bundleDebugJsAndAssets' of type org.gradle.api.tasks.Exec
task.dofirst不存在
解决:把apply from: "../../node_modules/react-native/react.gradle
和apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
都放在app/build.grade
中,app/build.grade
中引用的子模块不要加以上两行,不然就有上述错误。
react.gradle
主要是编译打包相关的,任务依赖这个app/build.grade
native_modules.gradle
是用于自动导包的
AutoLink
基于上个问题,看文档才发现60+引入了autolink。
对于有native
代码的第三方库,npm install
或者 yarn add
之后,不需要执行react-native link XXX
了。iOS
使用了cocoapods
来管理依赖,我们进入项目的iOS
目录,执行pod install
即可;安卓之前link
完,会在setting.gradle
、build.gradle
、MainApplication.java
三个文件添加引入,现在则都不需要了。
- iOS中,
podfile
中多了一下的代码
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
use_native_modules!
看了一下native_modules
的源码,是一个Ruby
脚本文件,就是执行pod install
时,执行了这个脚本
This is a function which is used inside your Podfile.
It usesreact-native config
to grab a list of dependencies, and pulls out.all of the ones
which declare themselves to be iOS dependencies (via having a Podspec) and automatically
imports those into your current target.
这个脚本利用react native config
这个cli
命令,来抓取项目的所有依赖,然后,把有podspec
文件的依赖自动的引入到cocoapods
中
- Android中,
setting.gradle
文件也有了变化:
rootProject.name = 'kjkDoctor'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle");
applyNativeModulesSettingsGradle(settings)
include ':app'
app/build.gradle
最后一行多了如下代码
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle");
applyNativeModulesAppBuildGradle(project)
applyNativeModulesSettingsGradle
和 applyNativeModulesAppBuildGradle
这两个gradle
方法都是在native_modules
中的脚本定义的
native_modules
是一个gradle
脚本,在/node_modules/@react-native-community
文件夹中,源码链接
- At build time, before the build script is run:
1⃣️.A first Gradle plugin (in settings.gradle) runs applyNativeModulesSettingsGradle method. It uses the package metadata from react-native config to add Android projects.
2⃣️.A second Gradle plugin (in app/build.gradle) runs applyNativeModulesAppBuildGradle method. It creates a list of React Native packages to include in the generated /android/build/generated/rn/src/main/java/com/facebook/react/PackageList.java file.- At runtime, the list of React Native packages generated in step 1.2 is registered by getPackages method of ReactNativeHost in MainApplication.java.
build阶段,在build脚本运行之前,先运行了setting.gradle
中的applyNativeModulesSettingsGradle
方法,这个方法利用react-native config
命令,拿到package metadata
,添加依赖到你的android
项目中.
然后,再运行了build.gradle
中的applyNativeModulesAppBuildGradle
方法,在/android/build/generated/rn/src/main/java/com/facebook/react/PackageList.java
中,生成了一系列的package
(之前是在mainApplication
中通过new xxxPackage()
),注意这个目录是android/build
下的目录,是排除版本控制的。
运行阶段,MainApplication.java
中的ReactNativeHost
方法会将上一步中生成的package
注册到项目中,这样就达到了与之前手动link
一样的效果了.
最后,还可以通过react-native.config.js
来定制化处理。
AndroidX的支持
报support.xx
不存在
解决:升级三方库,比如我升了一下几个
lottie、netinfo、viewpager、smartrefreshlayout、code-push、reanimated、react-native-fast-image
代码调整
Android
去除重复库,删掉之前的引入,避免和autolink
的重复。如果你使用 AS
3.5以上的版本,本地编译会自动帮你去除重复库,如果是3.5以下则会报错,所以当时遇到很奇怪的问题就是代码明明一样,为什么有的同学跑起来了,有的报错了。
frescoVersion
升到2.0+,支持webp
iOS
库升级,引用变化,如react-native-fast-image
升级,要按新api
调整,webp
重新注册
JS
引用库的变化
import deepDiffer from "react-native/lib/deepDiffer"
->
react-native/Libraries/Utilities/differ/deepDiffer
React.unstable_Profiler
->
React.Profiler
生命周期废弃
Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.
Warning: componentWillUpdate has been renamed, and is not recommended for use.
Warning: componentWillReceiveProps has been renamed, and is not recommended for use.
Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.
netinfo
发现新版本从offline
切到online
,不会更新状态,查官方说仅是模拟器的bug
,真机是好的
打包机问题
- iOS: 在打包机配
libwebp
的源 - iOS: xCode版本选择
- android(debug): 重复库问题
- android(release):重复资源、
watch
导致内存不足的问题
样式
Android不支持字重的设置
60以下版本是可以设置100-900,60之后只有normal(400)/bold(700),看issue说是官方的限制。
解决:需要使用自定义字体
未解决问题
- iOS时常卡死
同步问题解决进度:
问题定位到是一直在循环处理accessiblelabel
,注释掉就不卡了,最后用了个hack的方式临时解决,问题应该还是出现在使用方法上,官方Demo确实没问题
- iOS上执行
scrollTo
,其实变为执行scrollToEnd
同步问题解决进度:
这个问题相当诡异,和iOS同学一起定位到问题是MjRefrsh
这个库生成出来的调用数组并不是代码上的顺序,也就是和RCTScrollVIew
的顺序不一致,导致调用错乱了。
解决:最后发现是升级61.5,RCTScrollVIew
增加了两个属性的定义,加上就解决了。这个库没人维护了,之后RN升级都要注意同步一下,最后是换个库吧。
总结
- 过程还是很痛苦,主要是一大部分错误提示的都是无效信息,不好定位
- 结果还是很满意的,60+对安卓提升很明显,是肉眼可见的快了很多
- 感悟就是多学点端的知识很有必要