react-native-config 配置多包名&多环境 APKs 共存

以前都是准备几台不同的 android 手机安装不同环境的包,如果想一个手机安装不同环境的包,只能删了重新打然后重新安装。
解决问题的根本原因是,构建不同环境的包,假设我有三个环境

- Staging -> .env.Staging -> com.duolegamehelper.staging
- Alpha -> .env.alpha -> com.duolegamehelper.alpha
- Production -> .env.production -> com.duolegamehelper.production

那么我就打包的时候,通过不同的.env配置文件,动态的把包名和 APP 的名字打进去。
研究了半天,其实react-native-config是可以解决这个问题的,只不过需要修改打包的gradle脚本。

react-native-config

安装完了react-native-config以后,准备自己的不同环境的.env文件到项目的根目录。

➜  DuoleGameHelper git:(main) ✗ find . -type f -name ".env*"
./.env.production
./.env.alpha
./.env.staging
APP_PACKAGE_NAME='com.duolegamehelper.alpha'
APP_NAME='Alp-Duole'

iOS

iOS还没整明白,先整 android 的…

iOS比较特殊,就算是控制台能运行,将来打包还是得打开Xcode

这里我在网上找到了一个比较可行的方法。

Xcode 创建不同环境的scheme

  1. 复制几个和默认相同配置的scheme,然后build > Pre-actions,输入脚本

记得勾选Shared

rm "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"
echo ".env.alpha" > /tmp/envfile
"${SRCROOT}/../node_modules/react-native-config/ios/ReactNativeConfig/BuildXCConfig.rb" "${SRCROOT}/.." "${SRCROOT}/tmp.xcconfig"
  1. 创建Config

项目右键New file > 搜索Config > Save as iOS/Config

输入以下内容:

#include? "tmp.xcconfig"
  1. 注意配置Config

清除缓存

ios-cache-cleaner.sh

#!/bin/bash

# 清理 Xcode DerivedData 文件夹
echo "Cleaning Xcode DerivedData..."
rm -rf ~/Library/Developer/Xcode/DerivedData/*

# 清理 iOS build 文件夹
# 这个貌似不能删,run-ios貌似不能自己生成build文件夹
echo "Cleaning iOS build folder..."
# cd ios && rm -rf build && cd ..

# 清理 Watchman 缓存(可选,如果你遇到缓存问题)
echo "Cleaning Watchman cache..."
# watchman watch-del-all

构建脚本

package.json里面添加不同scheme的构建脚本

"run:ios:bate": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Bate\"",
"run:ios:staging": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Staging\"",
"run:ios:alpha": "./ios-cache-cleaner.sh && react-native run-ios --scheme \"JP-Alpha\"",

运行

chmod +x ios-cache-cleaner.sh
./ios-cache-cleaner.sh && react-native run-ios --scheme "JP-Alpha"

Android

修改build.gradle

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

def appName = project.env.get("APP_NAME") ?: "Def-Duole"
def timeStamp = new Date().format("yyyyMMdd_HHmmss")
def packageName = project.env.get("APP_PACKAGE_NAME") ?: "com.duolegamehelper"

修改 APP 的包名

这是这一讲的核心内容 …

- applicationId "com.duolegamehelper"
+ applicationId project.env.get("APP_PACKAGE_NAME")

修改 APP 在桌面上面展示的名字

resValue "string", "app_name", appName

修改 APP 构建时候的文件名

我想每次打包的时候,

`${环境名}-${APP名}-${时间戳YYYY-MM-DD HH:mm:ss}.apk`
android.applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
variant.outputs.all {
outputFileName = "${project.env.get("APP_NAME")}_${timeStamp}.apk"
}
}
}

打包命令

ENVFILE=.env.staging ./gradlew assembleDebug
ENVFILE=.env.production ./gradlew assembleRelease

react-native-config -> Config.xxx 读取不到配置

现在原生层面的问题解决了,但是之后会发现:

import Config from "react-native-config";
Config.APP_PACKAGE_NAME;
Config.APP_NAME;

都是拿不到东西的。

我们要明白react-native-config的本质是打包的时候生成BuildConfig,然后读取里面的内容。

翻看源代码发现,他是通过build_config_package来进行反射,

然后找到生成的BuildConfig

/Users/net.cctv3.i/DuoleGameHelper/android/app/build/generated/source/

➜  ~ cd /Users/net.cctv3.i/DuoleGameHelper/android/app/build/generated/source/
➜ source git:(main) ✗ tree
.
└── buildConfig
├── debug
│   └── com
│   └── duolegamehelper
│   └── BuildConfig.java
└── release
└── com
└── duolegamehelper
└── BuildConfig.java

也就是说,不管你打的什么环境的包,他读取的永远是com.duolegamehelper.BuildConfig
所以,

- def packageName = project.env.get("APP_PACKAGE_NAME") ?: "com.duolegamehelper"
- resValue "string", "build_config_package", packageName
+ resValue "string", "build_config_package", "com.duolegamehelper"

这个build_config_package是不同加环境后缀的。

useEffect(() => {
// console.log('Config.APP_PACKAGE_NAME: ', Config.APP_PACKAGE_NAME);
if (Platform.OS == "android") {
let constants = NativeModules.SystemModule.getConstants();
console.log("NativeModules.SystemModule.getConstants(): ", constants);
console.log("react-native-config: ", Config);
}
return function () {};
}, []);
{
"DEBUG": true,
"IS_NEW_ARCHITECTURE_ENABLED": false,
"VERSION_CODE": 1,
"APP_NAME": "Sta-Duole",
"APP_PACKAGE_NAME": "com.duolegamehelper.staging",
"IS_HERMES_ENABLED": true,
"BUILD_TYPE": "debug",
"APPLICATION_ID": "com.duolegamehelper.staging",
"VERSION_NAME": "1.0"
}

react-native-config 配置多包名&多环境 APKs 共存

https://www.cctv3.net/static/20240211/react-native-config.html

作者

江北饮马、江南折花

发布于

2024-02-11

更新于

2024-09-03

许可协议

评论