Yarn Workspaces monorepo下RN0.68.2安卓release启动崩溃如何解决
React Native 0.68 Yarn Workspaces monorepo 安卓Release启动闪退排查方案
报错提示无法加载index.android.bundle,本质只有两类原因:要么release构建时bundle没被打进APK的assets目录,要么Metro打包时没正确解析common公共包依赖,生成的bundle内容残缺。debug模式靠Metro实时热加载服务资源,不会触发本地bundle加载逻辑,所以能正常运行。
按以下顺序逐步排查修复:
第一步:确认APK内bundle文件状态
- 把生成的release APK拖入Android Studio的APK分析工具,查看
assets/目录下是否存在index.android.bundle文件 - 如果文件不存在:是Gradle构建时bundle任务路径配置错误,生成的bundle没被复制到APK打包目录
- 如果文件存在但体积异常小(低于100KB,RN 0.68空项目无业务代码的release bundle体积也在300KB以上):是Metro打包时没识别monorepo的workspace依赖,common目录代码没被打进bundle,导致内容残缺
第二步:修正Metro配置,解决公共包识别问题
默认Metro配置只会遍历mobile项目目录下的文件和依赖,无法识别上层workspace根目录的依赖和common公共包,这是monorepo场景最常见的坑:
- 修改
mobile/metro.config.js,显式添加监控目录和依赖解析路径,避免多实例冲突:
const path = require('path'); const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const monorepoRoot = path.resolve(__dirname, '..'); const config = { watchFolders: [ monorepoRoot, path.resolve(monorepoRoot, 'common'), ], resolver: { nodeModulesPaths: [ path.resolve(__dirname, 'node_modules'), path.resolve(monorepoRoot, 'node_modules'), ], resolveRequest: (context, moduleName, platform) => { // 强制所有文件引用同一份react、react-native实例,避免多实例报错 if (['react', 'react-native'].includes(moduleName)) { return context.resolveRequest( { ...context, disableHierarchicalLookup: true }, moduleName, platform ); } return context.resolveRequest(context, moduleName, platform); } }, transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, }; module.exports = mergeConfig(getDefaultConfig(__dirname), config);
- 在mobile目录下手动执行bundle打包命令,验证配置是否生效:
npx react-native bundle \ --platform android \ --dev false \ --entry-file index.js \ --bundle-output android/app/src/main/assets/index.android.bundle \ --assets-dest android/app/src/main/res \ --reset-cache
如果执行过程中报找不到common目录下模块的错误,调整watchFolders里的路径直到命令无报错,再检查生成的bundle体积是否符合预期。
第三步:修正安卓Gradle构建配置
配置nohoist后,RN的Gradle插件默认的路径识别逻辑会失效,导致release构建时要么跳过bundle打包任务,要么把bundle输出到错误路径:
- 修改
mobile/android/app/build.gradle中的react配置块,显式指定路径:
project.ext.react = [ enableHermes: false, // 项目开启Hermes的话改为true root: "../../", reactNativeDir: "../../node_modules/react-native", entryFile: "index.js", bundleInRelease: true, jsBundleDirRelease: "$buildDir/generated/assets/react/release", resourcesDirRelease: "$buildDir/generated/res/react/release", ] // 确认react.gradle引用路径正确 apply from: "../../node_modules/react-native/react.gradle"
- 在
mobile/android/gradle.properties中添加配置,强制release构建时执行bundle打包:
reactNative.bundleInRelease=true
第四步:全量清缓存后重新构建
缓存残留是配置不生效的最常见原因,改完配置后必须执行全量清理:
- 关闭所有Metro服务、Gradle构建进程
- 在monorepo根目录执行
yarn cache clean - 进入
mobile/android目录执行./gradlew clean - 回到mobile目录执行
cd android && ./gradlew assembleRelease
构建完成后安装APK即可正常启动。
补充注意点
- nohoist配置必须覆盖所有RN原生相关依赖,包含
**/react-native/**、**/@react-native-*/**、**/react-native-*/**,不要把这类依赖提升到根目录node_modules,否则安卓编译时会找不到原生模块 - common目录的TS代码不需要提前编译为JS,Metro原生支持TS/TSX文件解析,提前编译反而可能出现路径映射错误
- 开启Hermes引擎的场景,需要确认Hermes执行文件的引用路径也指向monorepo下正确的node_modules位置,否则会出现bundle字节码编译失败,同样会触发找不到有效bundle的报错
内容的提问来源于stack exchange,提问作者Joshua
相关产品推荐
相关产品推荐

