Over the years I've become increasingly more appreciative of solutions that leverage third-party solutions and snap them together to get something out the door quickly. Something that provides 80% of the value in 20% of the time. Sure, it's not as customizable as you would want it and may even be too restrictive for things you want to do in the future, but it gives you something that you can try out with very little upfront investment and when you have validated the idea you'll have a much easier time convincing people to allocate the time to go from 80 to 90 or maybe even 99%. Today we'll settle with the good ol' 80/20: A quick solution that anyone can spin up in a few minutes giving you an amazing boost to your development and subsequent review workflow.
If you're here you're probably familiar with Expo, in case you're not, I'd really encourage you to spin up a mobile app in less than 30 mins following the excellent instructions:
Let's Go! š
One amazing feature of Expo is that it allows you to essentially package up your React Native app as a JS bundle and open it up with the Expo Go client app, which very much acts like a web browser able to load up your React Native app given an exp:// URL.
Vercel provides us among other things the ability to create a preview deployment for every PR we create in our github repos allowing our fellow reviewers to test out the changes immediately without going through the hassle of checking out the branch, making a build, etc...
So the mission is as follows:
Create a JS bundle for Expo Go
Let Vercel deploy that bundle to a unique URL
Make the build easily accessible to reviewers and more in the Github PR
Profit!
1. Create a JS bundle for Expo Go
The expo-cli provides us with the expo export
command which is all we need to package up our app. In addition to the JS bundle per platform it also creates a directory with assets and two index.json files containing metadata such as the name of our app, version, references to assets and more:
dist
āāā android-index.json
āāā assets
āĀ Ā āāā 004c2bbb035d8d06bb830efc4673c824
āĀ Ā āāā 005579910f33d13e8c938016699bf6a1
āĀ Ā āāā 02bc1fa7c0313217bde2d65ccbff40d8
āĀ Ā āāā ..
āāā bundles
āĀ Ā āāā android-60b98bfb8440fc59be5e2db30ea0cbf7.js
āĀ Ā āāā ios-112ec78429fe8fcb60924fb5dc7c092b.js
āāā ios-index.json
The index files will serve as the entrypoint or URL for the Expo Go app. The export command has just one required argument, which is the public-url
. As we want to host this on Vercel we'll need the Vercel URL. We will be running the export command in the context of the builder provided by Vercel and as such we'll have a $VERCEL_URL
environment variable. Our final command to execute thus becomes:
expo export --public-url "https://$VERCEL_URL"
Let's create a file: .vercel/build_preview.sh
and add the above export script.
2. Deploy preview with Vercel
Once you've logged in to Vercel.com with you github user the steps are pretty straightforward:
Create new project
Select your Github org or account and import the repo
- Select your Vercel scope. For this demo I'll go with my "Personal Account", but at work you would select your organization:
Select the root of our project. No change required here. Just press next.
Next we'll override the build command and output directory.
- Press deploy and watch Vercel do its magic āØ. It will pull down your latest commit, install all dependencies and run the specified build command before making the contents of the output directory available on a unique URL!
Going back to our github repo we'll see a green tick indicating that the deployment succeeded!
Clicking on details we're sent to the Vercel dashboard for that deployment.
Here we see a preview of the website, which in our case isn't really a website. Pressing Visit, gives us a big fat 404 error, which, if we think about it makes sense. We don't really have anything resembling an index.html. So let's create one!
3. Make the App easily accessible to reviewers and more in the Github PR!
We'll add the following template .vercel/index.html.template
, which we fill out with the $VERCEL_URL placeholder.
<body></body>
<script type="text/javascript">
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
var isIPhone = ua.indexOf("iphone") > -1;
<!-- App Store Link for the Expo Go app -->
var link = isIPhone ? 'https://apps.apple.com/ao/app/expo-client/id982107779' : isAndroid ? 'https://play.google.com/store/apps/details?id=host.exp.exponent' : 'https://www.google.com/search?q=expo+go&oq=expo+go';
document.body.innerHTML += `
<h1>
Download <a href=${link}>Expo Go</a> and visit this link on your device
</h1>
`
<!-- Attempt to redirect to the Expo Go app -->
if(isIPhone){
window.location.href = 'exp://${VERCEL_URL}/ios-index.json';
}
if( isAndroid ){
window.location.href = 'exp://${VERCEL_URL}/android-index.json';
}
</script>
It will ensure we redirect iPhones and Android phones to their respective index.json files. In case we don't have the Expo Go app installed or we visit the URL from a laptop we show some instructions in the document body.
Lastly we add to our build script the instantiation of our template with the $VERCEL_URL and place it in the output directory. Our final build file now contains:
expo export --public-url "https://$VERCEL_URL"
sed -e "s/\${VERCEL_URL}/$VERCEL_URL/" .vercel/index.html.template > dist/index.html
Git commit and push the changes and in 2 minutes we have a preview link available!
4. Profit! š°
And there we have it! Vercel will build and deploy a preview for every change to our PR and people with access to the PR can click the preview links to preview that exact version of the app. You could even share the Vercel link with external stakeholders or colleagues who don't use GitHub.
The source for this example including build scripts can be found here:
5. One more thing...
Expo not only allows you to build apps for mobile, but you can also build and deploy the exact same code to Web! Feel free to venture into this on your own time, but if you're lazy (I for sure am), then sit tight and I'll see you in Part 2, where we'll build upon our existing solution to not only build and deploy a web version, but also integrate Storybook!