Updated January 26, 2016
React Native + CodePush
Originally publish on medium.com.
As technology changes articles get out of date. This post may be in that state now so be aware that things may not work exactly the same way. If you’re interested in me re-exploring this subject respond and let me know!
I’ve been building with React Native for a few months now — I wrote about my experiences a while back. Recently we’ve started a new mobile project and we chose to, again, use React Native on the client side and use Meteor as our DDP server.
One of the first things we took care of, the first thing after running “react-native init”, was establish a deployment process. Deployments on iOS aren’t like those that you may have gotten used to on the web. We can’t deploy to our servers and know that the next time a client connects they’ll have the latest code.
But it can be easier than going through App Store for each and every update. We’re going to get closer to hot code pushes that you may have gotten used to while developing with Meteor Cordova. I’m going to walk you through the technologies we’re using, how to get started, and when we use each type of update.
To preface the remainder of this post I want to specify that my experience has, to date, only been with iOS.
Technologies Used
Getting Started
I’m not going to copy down the docs here, React Native and Code Push both have documentation on how to get started. That documentation will stay more up to date than this blog post will. I’ll walk you through the process so you can have an idea of what to expect before diving into it for yourself.
After running through the steps outlined in the documentation I linked to you should be all set up on the tech side of things. But what can you expect in practice?
Updating — When, What, and How
Bug Fixes
When you find a bug in production code or, worse, users are experiencing an issue with your app. What can you do? You can try to expedite a bug fix through the app store review process. OR you could hot code push that sucker. You can get the fix into your user’s hands with minimal down time, and possibly without them even realizing there was a problem. This use case is supported by Apple’s Terms of Service (I’ll touch on this a bit more soon).
Native Code Changed
What I outlined above is a great example of using hot code push in your React Native app. But it does have its limitations, you can only update your assets and the JS bundle via hot code push. Basically this means that anything that you write, you can update OTA.
So why wouldn’t you always do so? Some code isn’t JS only. For example:
- Updating the version of React Native
- Updating some external React Native modules
- Changing your app icon or splash screen
Those are some instances that code has to be recompiled and thus can’t be shipped over the air. At times that can be a pain but it’s much less of a pain than before. I’ve found it to be pretty simple with a little bit of planning.
Major Updates (TOS Considerations)
Now what if we’re not modifying any native code but we’ve got a big update coming. Maybe you’ve just added a bunch of new features and you can’t wait to get them into your user’s hands? This is where you need to be careful.
When Meteor first announced built in support for Cordova they also announced the ability to update apps OTA, without having to go through the app store. This was very exciting but also brought up some concerns with Apple’s Developer Program Agreement. You can read that post here.
In short, you can ship updates over the air so long as those updates don’t change the purpose of the app. I approach this as bug fixes and minor design changes are okay. When it comes to a new feature though I put the app through the traditional app store review process. I like to play on the safe side here and explicitly have them review any new features.
Release Process
Enough talk, what’s the code look like? How do I get this code from my machine to the device’s of my user’s?
Over the Air Updates
The OTA updates are simple. I have to change one file and run two commands.
If your app is entirely client side the first step doesn’t apply to you. If you connect to a server then you’ll want to make sure to follow it.
- First things first — make sure you’re connecting to your production server! You don’t want to deploy an app that is pointing to ‘localhost:3000’.
- Bundle the app for production. To do this I add a script to my package.json called bundle, then all I have to do is run npm run bundle. That script contains the following:
react-native bundle — platform ios — entry-file index.ios.js — bundle-output ./release/main.jsbundle — assets-dest ./release — dev false.
CodePush has more in depth documentation on what configurations to use depending on your needs. My point here is that it can be wrapped up into a single, short script.
- Run ‘code-push release
./release ’. This command will get your newly bundled code up to CodePush. CodePush will then handle the delivery of the new app code to your users.
It’s a pretty simple process. CodePush gives you some options on how and when the user can actually make the switch from the old bundle to the new one, but I won’t be touching on that here.
App Store
So you’ve got over the air updates in place for bug fixes and minor changes. What’s the process look like when you have to go through the app store? It’s not fun…
- In Xcode, set the build target to “Generic iOS Device”.
- Again, make sure you’re connecting to your production server (if you’re connecting to a server).
- Update the jsCodeLocation in your AppDelegate.m to use the CodePush one (outlined in their docs from earlier).
- In Xcode, update the version and/or build number
- Run npm run bundle (script associated with this outlined earlier)
- In Xcode, go to “Product” > “Archive”
- When Archive is complete click “Submit to App Store”
- Go into your iTunes Connect account and add the necessary metadata
- Send it to Apple for review
10 . Get your new app into the hands of your users. Full of changes to native code, new icons, splash screens, etc.
I’m sure you could automate a few of the steps above but you get the point, there’s a lot more work when you have to go through the entire App Store review process. And the worst part is the part you have no control over — the amount of time you have to wait to get your updates reviewed.
Over the air updates with CodePush help this problem.
Other Notes
Adding collaborators on CodePush
We’ve got multiple collaborators on our projects that have permission to deploy updates. CodePush makes this pretty simple. There is one user that “owns” the project — we’re shipping their CodePush keys with the app. Let’s call them “Admin”. When we want to give a new developer permissions to do OTA updates here’s the process:
- NewDev: Install CodePush — npm install -g code-push-cli
- Admin: Create a new access token — code-push access-key add “
” - Admin: Give returned token to the new developer
- NewDev: Run code-push login — accessKey
- NewDev: Ensure that you can see the project by running code-push app ls. The app name should now be there.
This gives the Admin ability to allow other developers access to OTA updates without sharing their Github or Microsoft account information.
I hope you found this post helpful. If you have any questions about this or anything else React Native related tweet me (@spencer_carli) or email me (spencer at differential dot com).
Originally published at blog.differential.com on January 27, 2016.