Skip to content

Instantly share code, notes, and snippets.

@elnygren
Last active April 26, 2018 14:43
Show Gist options
  • Save elnygren/35e4125628a6f86002ff3596b1b97497 to your computer and use it in GitHub Desktop.
Save elnygren/35e4125628a6f86002ff3596b1b97497 to your computer and use it in GitHub Desktop.
React Native x CodePush (prod, staging)

Goal

(replace "Brand" with your app's name)

App             | BuildType / config  | CodePush     
----------------------------------------------------
Brand           | Debug               | <none>
Brand           | Release             | Production
Brand Beta      | Debug               | <none>
Brand Beta      | Release             | Staging
  • You can have Brand and Brand Beta both installed on iOS/Android simulator or physical device
  • Debug builds don't fetch CodePush bundle so it's easier to develop
    • it should be easy to make them fetch one though, so testing loading a bundle wouldn't always require making a Release build
  • Release builds fetch Staging (Brand Beta), Production (Brand) CodePush bundles respectively

Sources

https://medium.com/@ywongcode/building-multiple-versions-of-a-react-native-app-4361252ddde5 https://docs.microsoft.com/en-us/appcenter/distribution/codepush/react-native#multi-deployment-testing https://medium.com/@iammert/android-product-flavors-1ef276b2bbc1

iOS AppDelegate Example

  • Debug: fetch bundle from either custom location (NSUserDefaults) or use React Native's default (RCTBundleURLProvider)
  • Release: use CodePush
  #ifdef DEBUG
    // http://www.proreactnative.com/How-to-Develop-iOS-Apps-on-Linux-Using-React-Native/
    NSDictionary *appDefaults = @{@"host_preference": @"", @"port_preference": @""};
    [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
    NSString *host = [[NSUserDefaults standardUserDefaults] stringForKey: @"host_preference"];
    NSString *port = [[NSUserDefaults standardUserDefaults] stringForKey: @"port_preference"];

    if ([host length] != 0) {
      // Find JS from custom URL
      NSString * urlString = [NSString stringWithFormat: @"http://%@:%@/index.bundle?platform=ios&dev=true", host, port];
      jsCodeLocation = [NSURL URLWithString: urlString];
    } else {
      // How RN normally finds code
      jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    }
  #else
    // Use CodePush in release build
    jsCodeLocation = [CodePush bundleURL];
  #endif

Android Gradle

flavorDimensions "main"
productFlavors {
  main {
    dimension "main"
    applicationId 'com.sumpli'
  }
  beta {
    dimension "main"
    applicationId 'com.sumpli.beta'
  }
}

applicationVariants.all { variant ->
    println("Iterating variant: " + variant.getName())
    if (variant.getName() == "betaRelease") {
      variant.buildConfigField "String", "CODEPUSH_KEY", '"codepush-staging"'
    }
    if (variant.getName() == "mainRelease") {
      variant.buildConfigField "String", "CODEPUSH_KEY", '"codepush-production"'
    }
    ...
}

What NOT to do on iOS:

This mistake cost me about 8 hours :P

Per-configuration build products path, intermediate path

$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)

Framework search path

$PODS_CONFIGURATIONS_BUILD_DIR (recursive)

Library search path (recursive)

$(BUILD_DIR)/${CONFIGURATION}$(EFFECTIVE_PLATFORM_NAME)
$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)

PODS_CONFIGURATION_BUILD_DIR

$PODS_BUILD_DIR/Release$(EFFECTIVE_PLATFORM_NAME)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment