react-native 找不到符号问题的解决方案及溯源

1,704 阅读3分钟

问题介绍

最近(2022年11月4日)很多 react-native 项目上都出现了打包失败或者是开发环境无法启动的问题,报错内容很多:找不到符号、方法不会覆盖或者实现超类型的方法、程序包 XXX 不存在等。但点进源码可以发现几乎都是 com.facebook.react 下的某个包找不到导致的。

lALPJwnI0v8UxuLNCPDNC9g_3032_2288.png

有很多同学就直接去这个 npm 包的 issue 区搜索了,但其实这个崩溃不是对应包的问题,用 android Studio 打包就可以发现,所有使用 com.facebook.react 的原生模块有这个问题。

其实 react-native 官方已经对这个事件做出了解释和解决方案,可以看 Android build failures happening since Nov 4th 2022 · Issue #35210,下面所有的内容都可以在这个 issue 里找到。

解决方法

rn 官方为大于 0.63 的所有主要版本都准备了一个热更新补丁,所以如果你的 react-native 版本大于 0.63,就直接根据上面这个 issue 里找到对应的补丁版本,更新 package.json 内容,重新 yarn install,然后 cd android && ./gradlew clean 清理缓存,之后应该就恢复正常了。

如果你的版本低于 0.63,方法更简单,在 android\build.gradle 添加如下内容:

def REACT_NATIVE_VERSION = new File(['node', '--print',"JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version"].execute(null, rootDir).text.trim())

allprojects {
    configurations.all {
        resolutionStrategy {
            // Remove this override in 0.65+, as a proper fix is included in react-native itself.
            force "com.facebook.react:react-native:" + REACT_NATIVE_VERSION
        }
    }
    repositories {

大致意思就是获取到当前使用的 react-native 版本,然后把所有依赖项目的 rn 都覆盖成这个版本。

问题来源

问题的起因来自于早期的 react-native 模板项目,其中构建文件(.\android\build.gradle)中包含这么一行配置:

implementation 'com.facebook.react:react-native:+'

可以看到这里配置了 获取当前依赖库里能找到的最高等级的 react-native 版本

而在 0.70 版本之前,react-native 是通过 npm 分发的,对应的 jar 包在 node_modules\react-native\android\com\facebook\react\react-native 里。然后通过 android\build.gradle 中的如下配置引入这个包:

allprojects {
    repositories {
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        // ...
    }
}

这样一来,依赖项目实际能找到的最高等级的 react-native 包其实就是我们 package.json 里设定的版本。

但是这种动态版本其实还是不够稳的,如果开发者比较“灵活”的话,经常会出现一些 dev 团队很难复现的问题,最后原因几乎都是由于开发者的修改导致获取到的 react-native 版本有问题。

于是,dev 团队决定在 0.71 版本将模板项目里所有的 react-native:+ 移除并使用 Maven Central 仓库统一分发版本明确的 rn 依赖。在 2022 年 11 月 4 日,团队向 Maven Central 仓库推送了第一个 react-native 预览版本 0.71.0-rc0

但是由于几乎所有的 rn 项目里都或多或少会使用包含 react-native:+ 的依赖库,而现在构建时能找到的 rn 最高版本不再是之前 package.json 里配置的,而是最新的 0.71.0-rc0,版本的异常导致构建几乎 100% 会崩溃,问题就此爆发。

而 Maven Central 也不允许移除上传的包,所以 rn 团队只得选择针对之前的版本发布热更新补丁来解决这个问题。

更多问题的细节可以看 文首的 Issue,另外这个 issue 也在 react-native 的 issue 区置顶了,进去就能看到。

写在最后

其实这个问题很好解决的,点进 rn 的 issue 区就能看到。但是出于对官方团队的信赖,导致一直没往这方面想,碰巧项目上也刚调整了一些基础配置。在这个问题上就耽误了将近一天的时间。所以,问题越怪越要先去 issue 区里找,说不定不是自己的锅呢。