react-native-dynamic-bundle-restore
v0.7.4
Published
Fork 'mauritsd' module. Control which bundle is loaded from the Javascript side of your React Native app.
Downloads
219
Maintainers
Readme
react-native-dynamic-bundle-restore
fork: https://github.com/mauritsd/react-native-dynamic-bundle
What is this?
react-native-dynamic-bundle-restore is a library, similar to react-native-auto-updater and CodePush, that allows you to change the React Native bundle loaded by an application without updating the application itself (i.e. through the App Store or Google Play). You could use this functionality to, for example:
- Get app updates to users quicker.
- Make A/B-testing or gradual rollouts as easy as on the web.
react-native-dynamic-bundle-restore differs from react-native-auto-updater and alternatives in that it does not attempt to be a complete solution, only providing the bare necessities for switching bundles and reloading the app. This requires you to implement the logic to download and keep track of the bundles yourself, but does give you complete freedom in how you implement your updater or A/B testing logic.
work with reanimated 2
Install for Android
for version up to: 0.7.1 replace in file "MainApplication.java":
return RNDynamicBundleRestoreModule.launchResolveBundlePath(MainApplication.this);
to:
return RNDynamicBundleRestoreModule.launchResolveBundlePath(MainApplication.this, BuildConfig.VERSION_NAME);
import android.os.Bundle;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import org.killserver.reactnativedynamicbundlerestore.RNDynamicBundleRestoreModule;
replace:
public class MainActivity extends ReactActivity {
on:
public class MainActivity extends ReactActivity implements RNDynamicBundleRestoreModule.OnReloadRequestedListener {
and after this line:
private RNDynamicBundleRestoreModule module;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
MainApplication app = (MainApplication)this.getApplicationContext();
app.getReactNativeHost().getReactInstanceManager().addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) {
MainActivity.this.module = context.getNativeModule(RNDynamicBundleRestoreModule.class);
module.setListener(MainActivity.this);
}
});
}
@Override
protected void onStart() {
super.onStart();
if (module != null) {
module.setListener(this);
}
}
@Override
public void onReloadRequested() {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
MainActivity.this.getReactNativeHost().clear();
MainActivity.this.recreate();
}
});
}
import org.killserver.reactnativedynamicbundlerestore.RNDynamicBundleRestoreModule;
import org.killserver.reactnativedynamicbundlerestore.RNDynamicBundleRestorePackage;
import javax.annotation.Nullable;
and replace:
new ReactNativeHost(this) {
on:
new ReactNativeHost(this) {
@Nullable
@Override
protected String getJSBundleFile() {
return RNDynamicBundleRestoreModule.launchResolveBundlePath(MainApplication.this, BuildConfig.VERSION_NAME);
}
Install for IOS
add:
#import <RNDynamicBundleRestore.h>
@class RCTRootView;
after:
#import <UIKit/UIKit.h>
replace:
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
to:
@interface AppDelegate : UIResponder <UIApplicationDelegate, RNDynamicBundleRestoreDelegate>
replace:
@property (nonatomic, strong) UIWindow *window;
to:
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) NSDictionary *launchOptions;
replace:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"YOU_VERY_COOL_APPLICATION"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
to:
- (void)getRootViewForBundleURL {
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:self.launchOptions];
RNDynamicBundleRestore *dynamicBundle = [bridge moduleForClass:[RNDynamicBundleRestore class]];
dynamicBundle.delegate = self;
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"YOU_VERY_COOL_APPLICATION"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
}
- (void)dynamicBundle:(RNDynamicBundleRestore *)dynamicBundle requestsReloadForBundleURL:(NSURL *)bundleURL
{
[self getRootViewForBundleURL];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
InitializeFlipper(application);
#endif
self.launchOptions = launchOptions;
[self getRootViewForBundleURL];
return YES;
}
replace:
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
to:
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
NSURL *bundle = [RNDynamicBundleRestore resolveBundleURL];
if(bundle!=nil) {
return bundle;
}
Getting started
$ npm install react-native-dynamic-bundle-restore --save
or
$ yarn add react-native-dynamic-bundle-restore
Mostly automatic installation
$ react-native link react-native-dynamic-bundle-restore
Manual installation
iOS
- In XCode, in the project navigator, right click
Libraries
➜Add Files to [your project's name]
- Go to
node_modules
➜react-native-dynamic-bundle-restore
and addRNDynamicBundleRestore.xcodeproj
- In XCode, in the project navigator, select your project. Add
libRNDynamicBundleRestore.a
to your project'sBuild Phases
➜Link Binary With Libraries
- Run your project (
Cmd+R
)<
Android
- Open up
android/app/src/main/java/[...]/MainActivity.java
- Add
import org.killserver.reactnativedynamicbundlerestore.RNDynamicBundleRestorePackage;
to the imports at the top of the file - Add
new RNDynamicBundlePackage()
to the list returned by thegetPackages()
method
- Append the following lines to
android/settings.gradle
:
include ':react-native-dynamic-bundle-restore'
project(':react-native-dynamic-bundle-restore').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-dynamic-bundle-restore/android')
- Insert the following lines inside the dependencies block in
android/app/build.gradle
:
implementation project(':react-native-dynamic-bundle-restore')
Usage
import {
setActiveBundle,
registerBundle,
unregisterBundle,
reloadBundle
} from 'react-native-dynamic-bundle-restore';
/* Register a bundle in the documents directory of the app. This could be
* pre-packaged in your app, downloaded over http, etc. Paths are relative
* to your documents directory.
*/
registerBundle('a_b_test', 'bundles/a_b_test.bundle');
/* Set the active bundle to a_b_test. This means that on the next load
* this bundle will be loaded instead of the default.
*/
setActiveBundle('a_b_test');
/* Unregister a bundle once you're done with it. Note that you will have to
* remove the file yourself.
*/
unregisterBundle('a_b_test');
/* In some circumstances (e.g. the user consents to an update) we want to
* force a bundle reload instead of waiting until the next app restart.
* Note that this will have to result in the destruction of the current
* RCTBridge and its recreation with the new bundle URL. It is therefore
* recommended to sync data and let actions complete before calling this.
*/
reloadBundle();
/*
* clear all store about bundles(need for moving between versions)
*/
resetAllBundlesBetweenVersion();