First Time Deploying with React Native

If you are like me, and have excitingly got your hands on a contract to build a React Native app, or are building a React Native app for the first time, I think we can all agree bundling and deploying your app is not straight forward and well documented at this moment. So in an effort to save others the hours I spent getting my app to work (and as reference for myself next time), I’ll go through my journey to deployment.

Note: This is for bundling and deploying an iOS app to the App Store.

1. Using the Offline Bundle

Cool! You’ve completed the app for version 1.0. Things are looking good, and so the best place to head next is to have a look at the React Native docs for “Running On Device”. Follow the steps under Using Offline Bundle. It’s pretty straight forward, open up AppDelegate.m, comment the line that points to the dev server and instead uncomment the local location for the bundle.

Example AppDelegate.m file

If you confused by step 3 in the docs, below demonstrates how you can get to the scheme settings.

Accessing the Scheme menu in Xcode

Sweet! The app now knows to load the local bundled js file. However, this mysterious main.jsbundle file that we told the app to use doesn’t exist. So I’m still left with one main question.

How do I create an offline bundle?

2. Creating an Offline Bundle

The answer is the local cli that lies within the react-native npm package. To generate the main.jsbundle file, run the following:

node node_modules/react-native/local-cli/cli.js bundle --entry-file='index.ios.js' --bundle-output='./ios/YourApp/main.jsbundle' --dev=false --platform='ios' --assets-dest='./ios'

There is a lot happening in this command, so make sure to checkout this great reference in the react-native cli source code, which describes each option below.

— entry-file=’<path to your index.(ios|android).js file>

— bundle-output=’<path of where main.bundlejs will be created>’

— dev=false (bunch of perf optimisations are made when false)

— platform=’ios’

— assets-dest=(there is more detail a few paragraphs below)

No one wants to write that super tedious command every time, so chuck it into a npm script instead!

Now you can do npm run build:ios. The packager should start up, bundle your js code and output a file called “main.jsbundle” at ./ios/<YourApp>/. The final step is to add this file to the <YourApp> folder within the Xcode project.

“main.jsbundle” needs to be located in the same folder as main.m

3. Dealing with Assets

This is what stumped me for a little bit. How to get images to work with the offline bundle as they previously where without a hitch when the app pointed to the js bundle from the dev server (before we un/commented those lines in the AppDelegate.m). First let’s look at how React Native handles images. If you read the docs for images, the first line reads as:

As of 0.14, React Native provides a unified way of managing images in your iOS and Android apps.

Awesome, cross platform images for the win! If you’ve been using require(‘../img/some-img.png’) in your app, you understand that it simply treats your images just as if they were js modules. The key to all this working with the an offline bundle is the — assets-dest option in the react-native bundle command.


This option tells the bundler the location of where you want to copy over all the assets (in this case just images). The path I used is ./ios, which mean this handy folder called “assets” was generated for me inside the ios folder.

The only thing left to do is to add this “assets” folder to the Xcode project. This can be done by right clicking on the project in the left side bar, and selecting “Add Files to <Your App>”.

Note, in order to get the images to work correctly, I needed to select the “Create folder references” option instead of “Create groups” when adding the assets folder. This can also apply when adding “main.jsbundle” to the project.
Dialogue that appears when clicking “Add Files…”

If you cannot can’t see these options, you need to click the “Options” button first in the bottom left of the popup menu. For a more in depth look at the differences between Folder References and Create Groups, checkout this article

And That’s It!

As long as you’ve got your cert and provisioning profiles set up correctly, if you don’t Ionic has some really easy docs to follow, you can now run the app on a device and archive the build ready to be uploaded to iTunes Connect!