React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建

在 React Native 开发过程中,通常我们依赖于已发布 React-Native 的 NPM 包。然而,在某些特定情况下,比如虽然RN已经修复了一些bug,但是你的项目无法立刻升级,这就需要从源代码构建 React Native,特别是在进行深度定制或者调试时。本文将介绍如何从 React Native 的 Android 部分源码 ReactAndroid 来构建 React Native。

如果你是React-Native比较新的版本(版本号大于0.72.x),可能本文对你的帮助有限,你只需要按照官方的文章进行即可:reactnative.dev/contributin...,当然你也可以继续看看,或许构建的错误都有共同之处。

接下来就来说说,旧版本的该怎么操作:第一步找官方教程,第二步解决官方教程坑。

按照官方教程操作

如果你是直接搜索,大概率找到的是新版本的构建,而旧版本通常比较难找到,找的的可能也是中文官网上比较老的版本说明,这里贴下文章:github.com/facebook/re...

下面只挑重点的来讲,默认你已经有了自己的RN项目,现在只是希望自己的项目能用到node_modules里面的源码,从而达到自己修改源码就可以应用到自己项目

下面我就概括一下:

安装并设置NDK和SDK

**步骤1:**通过终端设置环境变量。

  • bash:<font style="color:rgb(31, 35, 40);">.bash_profile</font>或者<font style="color:rgb(31, 35, 40);">.bashrc</font>
  • zsh:<font style="color:rgb(31, 35, 40);">.zprofile</font>或者<font style="color:rgb(31, 35, 40);">.zshrc</font>

例子:

plain 复制代码
export ANDROID_SDK=/Users/your_unix_name/android-sdk-macosx
export ANDROID_NDK=/Users/your_unix_name/android-ndk/android-ndk-r20b

步骤2: 修改你的<font style="color:rgb(31, 35, 40);">local.properties</font>,路径是你项目下<font style="color:rgb(31, 35, 40);">android/local.properties</font>,没有就新建

添加内容(如果已经设置就忽略):

plain 复制代码
sdk.dir=/Users/your_unix_name/android-sdk-macosx
ndk.dir=/Users/your_unix_name/android-ndk/android-ndk-r20b

如果你没有这两个路径或者不知道下载过没,打开Android Studio去找。

修改项目安卓打包的相关配置

  • 修改<font style="color:rgb(31, 35, 40);">android/build.gradle</font>,增加下载相关依赖

增加两行配置(带+号的),不过一般能的项目都有了,有了就别改动了,这个配置只是下载使用的

plain 复制代码
buildscript {
    // ...
    dependencies {
        // Make sure that AGP is at least at version 7.x
        classpath("com.android.tools.build:gradle:7.0.4")

+       classpath("com.facebook.react:react-native-gradle-plugin")
+       classpath("de.undercouch:gradle-download-task:5.0.1")
    }
}
  • 修改 <font style="color:rgb(31, 35, 40);">android/settings.gradle</font>,引用<font style="color:rgb(31, 35, 40);">node_modules/react-native/ReactAndroid</font>目录的源码

在文件底部增加下面的代码:

plain 复制代码
// ...省略其他

include(":ReactAndroid")
project(":ReactAndroid").projectDir = new File('../node_modules/react-native/ReactAndroid')

//注意:官方是没有hermes-engine,但是我的项目有用到所以也添加,你可以先不加,打包如果报错之后再加这两行
include(':ReactAndroid:hermes-engine')
project(':ReactAndroid:hermes-engine').projectDir = new File(rootProject.projectDir, '../node_modules/react-native/ReactAndroid/hermes-engine')
  • 修改 android/app/build.gradle,项目用<font style="color:rgb(31, 35, 40);">node_modules/react-native/ReactAndroid</font>目录的源码构建

找到<font style="color:rgb(31, 35, 40);">dependencies</font>配置,把 <font style="color:rgb(31, 35, 40);">implementation 'com.facebook.react:react-native:+'</font> 改成 <font style="color:rgb(31, 35, 40);">implementation project(':ReactAndroid')</font>

plain 复制代码
dependencies {

    //implementation 'com.facebook.react:react-native:+' 需要注释掉
    implementation project(':ReactAndroid')

    // ...
}

还是同一个文件,找到configurations.all,增加下面的配置:

plain 复制代码
 configurations.all {
      resolutionStrategy {
          dependencySubstitution {
              //这主要是让第三方React Native库,也使用我们指定的本地库,不然它们会使用预编译的库,会报错
              substitute module("com.facebook.react:react-native:+") with project(":ReactAndroid")
          }
      }
  }

开始试运行

  1. 清理之前的缓存: 终端执行./gradlew clean
  2. 然后运行:终端执行yarn android

如果你能运行,恭喜你,那真是太过顺利了,不然可能会出现一些问题,你可以继续往下看看

解决打包过程中的失败

打包过程中,任务下载各种包失败

Node包中使用的库也会依赖各种包,这种任务在你yarn android的日志中都会体现:

plain 复制代码
//ReactAndroid相关的下载任务
Task :ReactAndroid:downloadFmt UP-TO-DATE
Download https://github.com/fmtlib/fmt/archive/6.2.1.tar.gz


//react-native-reanimated库相关的下载任务
Task :react-native-reanimated:downloadBoost UP-TO-DATE
Download https://boostorg.jfrog.io/artifactory/main/release/0.70.10/source/boost_1_76_0.tar.gz

如果发现包下载失败,自己复制url到浏览器试试,检查是否可以访问,可能需要科学上网,如果科学砂锅女王还是不行就去镜像网站上查找,然后去node_modules对应的目录下修改<font style="color:rgb(31, 35, 40);">android/build.gradle</font>,可以指定可以下载的路径,这里情况分两种,一种是你依赖的第三方库(比如:react-native-reanimated),一种是ReactAndroid任务

  • 前者你去node_modules/<font style="color:rgb(31, 35, 40);">react-native-reanimated/android/build.gradle</font> 修改对应的url,一定要能下下来包,下载下来的内容在node_modules/<font style="color:rgb(31, 35, 40);">react-native-reanimated/android/build/downloads</font>中,你也可以检查是否下载下来的有内容
  • 后者要到node_modules/react-native/ReactAndroid/build.gradle修改,原理都是一样的

buildHermes失败

在日志中会出现对应任务,如果这个任务跑过,基本就成功了

plain 复制代码
Task :ReactAndroid:hermes-engine:buildHermes

只需要关注失败!!也就是 error提示,警告不用管。

之前我碰到过一个异常:

plain 复制代码
node_modules/react-native/sdks/hermes/lib/Support/Semaphore.cpp:35:3: 
error: use of undeclared identifier 'assert' 35 | assert(semPtr_ != nullptr && "sem_open should have succeeded");

GPT交流了一下发现是node_modules/react-native/sdks/hermes/lib/Support/Semaphore.cpp代码中使用了 assert,但没有包含相应的头文件。在 C++ 中,assert 是定义在 <cassert>(C++)或 <assert.h>(C)的头文件中的。如果这个头文件没有被正确包含,就会导致该错误。

但是当你欣喜若狂去修改了却发现并没有用,因为每次yarn android都会重新下载sdks/hermes的内容,所以要先把hermes的内容全都复制出来,修改Semaphore.cpp文件,然后打包成tar文件,放到自己服务器的上,再按照第一步的方式去修改任务的下载链接。

hermes的下载 task :ReactAndroid:hermes-engine:downloadHermes UP-TO-DATE,所以要去查找downloadHermes这个任务,最后发现是ReactAndroid/hermes-engine/build.gradle中的,所以找到并修改即可。

最后还要测试一下生成模式下是否成功,还遇到过生成下载的hermes不是最新的,需要修改hermes下载包名

plain 复制代码
 task downloadHermes(type: Download) {
-    dest(new File(downloadsDir, "hermes.tar.gz"))
+    dest(new File(downloadsDir, "myHermes.tar.gz"))
 }

总结

上面只是总结了自己所遇到的疑难杂症,基本上所有的问题通常出现在库的第三方依赖,所以要学会去各个库修改第三方依赖,也就是修改他们的build.gradle文件。

应用源码改动

上面只记录了如何从源码编译,当你成功之后,如果你期望你修改的源码可以应用到项目中,可以在生产使用,那有两种解决方案:

  1. 发布你自己的ReactNative版本,然后在package.json修改依赖。那就按照教程来:github.com/facebook/re...
  2. yarn补丁管理: yarn patch-package react-native,就是把你之前在node_modules/react-native/当成个补丁提交,这样可以跟随着项目一起,但缺点在于改动的点不够明确
相关推荐
大数据追光猿9 分钟前
Python中的Flask深入认知&搭建前端页面?
前端·css·python·前端框架·flask·html5
莫忘初心丶12 分钟前
python flask 使用教程 快速搭建一个 Web 应用
前端·python·flask
横冲直撞de43 分钟前
前端接收后端19位数字参数,精度丢失的问题
前端
我是哈哈hh44 分钟前
【JavaScript进阶】作用域&解构&箭头函数
开发语言·前端·javascript·html
摸鱼大侠想挣钱1 小时前
ActiveX控件
前端
谢尔登1 小时前
Vue 和 React 响应式的区别
前端·vue.js·react.js
酷酷的阿云1 小时前
Vue3性能优化必杀技:useDebounce+useThrottle+useLazyLoad深度剖析
前端·javascript·vue.js
神明木佑1 小时前
HTML 新手易犯的标签属性设置错误
前端·css·html
老友@1 小时前
OnlyOffice:前端编辑器与后端API实现高效办公
前端·后端·websocket·编辑器·onlyoffice
bin91531 小时前
DeepSeek 助力 Vue 开发:打造丝滑的缩略图列表(Thumbnail List)
前端·javascript·vue.js·ecmascript·deepseek