React Native 多环境配置

栏目: IOS · Android · 发布时间: 5年前

内容简介:通常,App 开发、部署会涉及多个环境,譬如开发、测试、预发布、生产等环境。为了避免打错包,我们需要使用科学的方法来切换环境。按照下图指引,分别 Duplicate "Debug" Configuration 和 Duplicate "Release" Configuration,创建 Debug production 和 Release production 两个 configuration。如下图所示,点击

通常,App 开发、部署会涉及多个环境,譬如开发、测试、预发布、生产等环境。为了避免打错包,我们需要使用科学的方法来切换环境。

使用 Configuration 和 Scheme 来实现 iOS 工程的多环境配置

按照下图指引,分别 Duplicate "Debug" Configuration 和 Duplicate "Release" Configuration,创建 Debug production 和 Release production 两个 configuration。

React Native 多环境配置
React Native 多环境配置

创建环境变量

如下图所示,点击 + 按钮,添加用户定义设置

React Native 多环境配置

我们添加 BUILD_TYPE 和 ENVIRONMENT 这两个自定义设置,结果如图所示:

React Native 多环境配置

打开 Info 选项卡

React Native 多环境配置

添加一个名为 AppSettings 的字典,它有两个字段: BUILD_TYPEENVIRONMENT ,它们的值分别为 $(BUILD_TYPE)$(ENVIRONMENT)

React Native 多环境配置

点击 Scheme 按钮,创建新的 scheme,命名为 MyApp qa ,中间有个空格,这个 scheme 纯粹是对 MyApp 的复制

点击 Scheme 按钮,创建新的 scheme,命名为 MyApp production ,中间有个空格。

React Native 多环境配置

编辑 MyApp production, 把左边 Run Test Profile Analyze Archiv 每个选项卡中的 Build Configuration 设置为对应的 production 版本。

React Native 多环境配置

创建原生模块

现在,我们通过切换 scheme,就能切换 BUILD_TYPE 和 ENVIRONMENT 这些变量的值。为了让 RN 能够知道这些值,我们需要借助原生模块。

选中 MyApp 目录,右键打开菜单,选择 New File...

React Native 多环境配置

在弹出的界面中,确定 Cocoa Touch Classs 处于选中状态,点击 Next

React Native 多环境配置

创建一个名为 AppIno(名字随意) 的类,然后 Next

React Native 多环境配置

选择类文件要存放的目录,在这个示例工程里,我们把它放在 MyApp 目录下

React Native 多环境配置

点击 Create 完成创建

编辑原生模块

编辑 AppInfo.h 文件

#import <React/RCTBridge.h>

NS_ASSUME_NONNULL_BEGIN

@interface AppInfo : NSObject <RCTBridgeModule>

@end

NS_ASSUME_NONNULL_END
复制代码

编辑 AppInfo.m 文件

#import "AppInfo.h"

@implementation AppInfo

RCT_EXPORT_MODULE(AppInfo)

+ (BOOL)requiresMainQueueSetup {
  return YES;
}

- (dispatch_queue_t)methodQueue {
  return dispatch_get_main_queue();
}

- (NSDictionary *)constantsToExport {
  NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
  NSMutableDictionary *settings = [[info objectForKey:@"AppSettings"] mutableCopy];
  NSString *versionName = [info objectForKey:@"CFBundleShortVersionString"];
  NSNumber *versionCode = [info objectForKey:@"CFBundleVersion"];
  NSString *bundleId = [info objectForKey:@"CFBundleIdentifier"];
  [settings setObject:versionName forKey:@"VERSION_NAME"];
  [settings setObject:versionCode forKey:@"VERSION_CODE"];
  [settings setObject:bundleId forKey:@"APPLICATION_ID"];
  return settings;
}

@end
复制代码

在上面这个原生模块中,我们导出了 BUILD_TYPE ENVIRONMENT VERSION_NAME VERSION_CODE APPLICATION_ID 等变量,这些变量,我们稍后可以在 RN 模块中读取。

使用 flavor 来实现 Android 工程的多环境配置

添加 flavor

编辑 android/app/build.gradle 文件,添加 flavor

android{
    flavorDimensions "default"
    productFlavors {
        qa {

        }
        production {

        }
    }
}
复制代码

就这样,我们创建了 qa 和 production 两个环境,我们通过原生模块将相关环境变量导出。

创建原生模块

打开 AndroidStudio,如图所示,创建一个名为 AppInfo 的 java 文件

React Native 多环境配置
React Native 多环境配置

编辑该文件

package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class AppInfo extends ReactContextBaseJavaModule {

    public AppInfo(@Nonnull ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Nonnull
    @Override
    public String getName() {
        return "AppInfo";
    }

    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        HashMap<String, Object> constants = new HashMap<>();
        constants.put("ENVIRONMENT", BuildConfig.FLAVOR);
        constants.put("VERSION_NAME", BuildConfig.VERSION_NAME);
        constants.put("VERSION_CODE", BuildConfig.VERSION_CODE);
        constants.put("APPLICATION_ID", BuildConfig.APPLICATION_ID);
        constants.put("BUILD_TYPE", BuildConfig.BUILD_TYPE);
        return constants;
    }
}
复制代码

在上面的文件中,我们通过名为 AppInfo 的模块,导出了 BUILD_TYPE ENVIRONMENT VERSION_NAME VERSION_CODE APPLICATION_ID 等变量。

如图,创建一个叫 AppPackage 的文件

React Native 多环境配置

编辑如下:

package com.myapp;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;

public class AppPackage implements ReactPackage {
    @Nonnull
    @Override
    public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new AppInfo(reactContext));
        return modules;
    }

    @Nonnull
    @Override
    public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
复制代码

修改 MainApplication.java 文件

package com.myapp;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    // 添加本项目需要导出的 package
                    new AppPackage()
            );
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}
复制代码

到目前为止,我们就已经创建了原生模块,并导出了相关变量。

在 React Native 代码中读取原生代码导出的环境变量

在项目根目录下创建名为 app 的文件夹,在里面创建名为 AppInfo.ts 的文件,编辑如下

// AppInfo.ts
import { NativeModules } from 'react-native'
const AppInfo = NativeModules.AppInfo

export const ENVIRONMENT: string = AppInfo.ENVIRONMENT
export const VERSION_NAME: string = AppInfo.VERSION_NAME
export const VERSION_CODE: number = AppInfo.VERSION_CODE
export const APPLICATION_ID: string = AppInfo.APPLICATION_ID

export const BUILD_TYPE_DEBUG = 'debug'
export const BUILD_TYPE_RELEASE = 'release'
export type BUILD_TYPE_DEBUG = typeof BUILD_TYPE_DEBUG
export type BUILD_TYPE_RELEASE = typeof BUILD_TYPE_RELEASE
export const BUILD_TYPE: BUILD_TYPE_DEBUG | BUILD_TYPE_RELEASE = AppInfo.BUILD_TYPE
复制代码

就这样,我们读取到了原生模块导出的变量,可以在有需要的地方使用这些变量

如何切换环境

现在,我们有了 qa 和 production 两个环境,那么如何切换环境呢?

iOS 在点击 Run 按钮之前,选择对应环境的 scheme 即可,譬如选择 MyApp qa 就是选择了 qa 环境。

Android 则通过 ./gradlew assembleQaRelease./gradlew assembleProductionRelease 分别可以打 qa 和 production 环境的包。

不同环境还可以配置不同的 App icon 和 App name,有兴趣的同学可以去研究下。

切换环境如此容易,还担心打错包吗?

本文是 React Native 工程化实践 系列文章中的一篇


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

沸腾十五年

沸腾十五年

林军 / 中信出版社 / 2009-7 / 59.00

覆雨翻云的中国网事; 荡气回肠的产业传奇;虚拟世界的真实讲述;万象网络的还原走笔。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本书记录了一群在中国创造属于自己历史的人和他们的故事,他们是中国互联网自1995年兴起的波澜壮阔中的弄潮儿和财富新贵的代表:马化腾、丁磊、张朝阳、马云、陈天桥、李彦宏、史玉柱、田溯宁、张树新、王志东、王峻涛、雷军、......一起来看看 《沸腾十五年》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具