Search code examples
react-nativecode-pushreact-native-code-push

resolving assets relative to react native bundle file outside project root


Issue(android): where to place image assets relative to js bundle file if bundle file is located outside of project root?

We have a small service where we upload JS bundles on each build. So, for example we have app com.example, if we want to update our app(while app review is pending in the app store) then we:

  1. download JS bundle to android path /data/data/com.example/files/bundle/android.bundle
  2. set this bundle as active via https://github.com/mauritsd/react-native-dynamic-bundle

Imagine that in the react App component we have a single image with path star.png.

When we activate a new bundle then star image is not shown.

I've checked the image path via https://reactnative.dev/docs/image#resolveassetsource in release build and the image uri resolves just to star.

So I tried the following file structures:

№1

data
--data
----com.example
------files
--------bundle
----------android.bundle <= dynamic bundle from remote server
----------star // <= our image

№2

data
--data
----com.example
------files
--------bundle
----------android.bundle <= dynamic bundle from remote server
----------star.png // <= our image

But still image is not shown if the bundle file is outside of the project root.

Questions:

  1. What am I doing wrong? https://github.com/Microsoft/react-native-code-push somehow managed to solve it.
  2. Is ios solution the same one as for android?

Thanks in advance


Solution

  • Bundle assets should be placed in the same folder where js bundle file lives(tested only on android).

    You can always get bundle asset path via https://reactnative.dev/docs/image#resolveassetsource.

    How to test:

    1. Put an image star.png to the project root.
    2. Create a react native app with the following code:
    import React from 'react';
    import {
      SafeAreaView,
      Text,
      StatusBar,
      Image
    } from 'react-native';
    import Star from './star.png';
    
    const App: () => React$Node = () => {
    
      const r = Image.resolveAssetSource(Star);
      console.log(r);
    
      return (
        <>
          <StatusBar barStyle="dark-content" />
          <SafeAreaView>
            <Text>TestAssetsApp</Text>
            <Image
              style={{width: 50, height: 50}}
              source={Star}
            />
          </SafeAreaView>
        </>
      );
    };
    
    export default App;
    
    
    1. Set bundle path in your MainApplication.java(my app package is called com.testassetsapp):
    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() {
              @SuppressWarnings("UnnecessaryLocalVariable")
              List<ReactPackage> packages = new PackageList(this).getPackages();
              // Packages that cannot be autolinked yet can be added manually here, for example:
              // packages.add(new MyReactNativePackage());
              return packages;
            }
    
            @Override
            protected String getJSMainModuleName() {
              return "index";
            }
    
            // Add this method
            @Override
            protected String getJSBundleFile() {
              return "/data/data/com.testassetsapp/files/android.bundle";
            }
          };
    
    1. Create android JS bundle and assets via:
    react-native bundle --platform android --dev false --entry-file index.js --bundle-output android.bundle --assets-dest assets
    
    1. Install debug version via:
    cd android && ./gradlew installDebug
    

    NOTICE: test only via ./gradlew installDebug without metro bundler running as it always rewrites bundle path.

    Now if you run the app you will get an error "Bundle not found".

    1. Upload android.bundle file to /data/data/com.testassetsapp/files/android.bundle

    Now if you run the app it should start. But star image is not yet displayed.

    1. Upload bundle files from the assets folder to /data/data/com.testassetsapp/files so app data structure should be the following: enter image description here

    Now if you restart the app star image should be displayed.