在客户端开发中,配置 Flavor 是必不可少的环节。Android 可以通过 flavor 配置,flutter 可以通过 –dart-define 配置。 ReactNative 相对麻烦一些,一是编写 RN 原生模块将原生端配置好的 flavor 传输到 RN 端。 二是使用 react-native-config 库,它其实就是自动干了一所需要的事情。

下面仅针对 Android 项目,使用第二种方案创建开发环境和生产环境,更简单快捷。

  • 通过 react-native-config 能读取到 BuildConfig 文件中的所有内容。
  • .env.xxx 文件中配置的属性也会出现在 BuildConfig.java 中,可以在原生端使用

添加依赖

npm install react-native-config

创建 .env 文件

在项目根目录创建两个配置文件:

.env.development

API_URL=https://test-app.imaracash.co
API_KEY=xxxxxxxxxx

.env.production

API_URL=https://prod.imaracash.co
API_KEY=yyyyyyyyyyy

配置 android/app/build.gradle

apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"

project.ext.envConfigFiles = [
    dev: ".env.development",
    prod: ".env.production",
]

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

android {
    flavorDimensions "env"
    productFlavors {
        dev {
            dimension "env"
        }
        prod {
            dimension "env"
        }
    }
}

配置 package.json 命令

修改package.json 中的 run 脚本指定默认的 flavor -- mode 参数用于指定 buildVariant(根据配置的 flavor 为 devDebug, devRelease, prodDebug, prodRelease)

{
  "scripts": {
    "android": "react-native run-android --mode devDebug"
    // ...
  }
}

构建 apk 或 aab 时和普通的 Android 项目一致,也不需要做特殊处理:

# 构建测试包
cd android
./gradlew assembleDevRelease

# 构建aab
cd android
./gradlew clean bundleProdRelease

需要注意构建时的输出,一般会有这类日志,表示已应用了配置

> Configure project :app
Reading env from: .env.development

项目中使用

import Config from "react-native-config";

Config.API_URL; // 'https://prod.imaracash.co'
Config.API_KEY; // 'yyyyyyyyyyy'

但是默认情况下,Config 对象是没有代码提示的,我们并不知道 Config 中有什么东西。我们有两种方案可以解决,我更推荐使用方案 2,因为方案 2 更灵活,可以塞入其他配置,例如下面我额外添加了 LANGUAGECOUNTRY_CODE 两个固定的配置。

方案 1:使用类型定义文件 react-native-config.d.ts

declare module "react-native-config" {
  export interface NativeConfig {
    API_URL?: string;
    API_KEY?: string;
    FLAVOR?: string;
    APPLICATION_ID?: string;
    VERSION_CODE?: string;
    VERSION_NAME?: string;
  }

  export const Config: NativeConfig;
  export default Config;
}

方案 2:自定义 Config

import RNConfig from "react-native-config";

export interface AppConfig {
  LANGUAGE: string;
  COUNTRY_CODE: number;
  IS_DEV: boolean;
  API_HOST?: string;
  API_KEY?: string;
  APPLICATION_ID?: string;
  VERSION_CODE?: string;
  VERSION_NAME?: string;
}

export const Config: AppConfig = {
  LANGUAGE: "en",
  COUNTRY_CODE: 234,
  IS_DEV: RNConfig.FLAVOR === "dev",
  API_HOST: RNConfig.API_HOST,
  API_KEY: RNConfig.API_KEY,
  APPLICATION_ID: RNConfig.APPLICATION_ID,
  VERSION_CODE: RNConfig.VERSION_CODE,
  VERSION_NAME: RNConfig.VERSION_NAME,
};

export default Config;