Better Apps By Default
When you’re finished, run simple commands to compile and run the project on any major platform: Android, iOS, macOS, server-side rendering, Web, and Windows. When you’re ready to release your app to the world, you’ll find some optimizations are built-in, as well as a few tools to help you analyze and test your app. From there it’s up to you to sign and publish the app.
Starting New Projects
When I start new front-end projects I face the same problems every time:
- I have to set up a bunch of build tools before I can work on the app
- Most starter projects cover some features I want and some I don’t, and never cover many platforms
- No matter if I start from scratch or use a boilerplate, there are head-scratching hours/days of optimization and tuning ahead before compiled builds are production ready
- Adding platforms, features, or code-base complexity later on frequently leads to refactoring in order to stay organized. What if it was organized with this complexity in mind to start?
What should a boilerplate do?
So I set out to create a boilerplate that I could turn to again and again. It has to:
- Work well on every platform (native and web)
- Get you to production with minimal hassle (out of the box optimized for real-world use)
- Make built-in platforms and features by default disabled, but easy to enable. Make the developer opinionated where possible, not the boilerplate.
- Be easy to write core code across platforms and easy to add platform-specific code. React Native handles most of this but it’s challenging to set up key common features. Well-organized navigation and data persistence need to be built-in. Community libraries, properly implemented, make this a reality.
- Offer an (optional) command line interface that standardizes common commands across platforms. In other words, prevent these questions from happening: How do I run my project on Windows again?? Was it
- Assist in basic quality assurance with linting, testing, and reporting built-in. Make it straightforward to write standardized code, test platforms over time, and analyze the end results over time (bundle weight, usability testing, etc)
I specifically did not try to solve problems which vary too much between projects and machines:
- Platform SDK setup (don’t attempt to set up a native platform for someone, like Android SDK or Universal Windows Platform SDK)
- Deployment/publishing of apps (everyone has their own best way of releasing an app to the world)
- Optimizations that incur too large a maintenance cost. Therefore, boilerplate optimizations should be set and forget or opt-in.
A New Boilerplate
With those issues in mind, and a bit of elbow grease, I created Universal Native Boilerplate. Then I used it to create an app to make sure it worked as expected. These are the features that come built-in:
- React and React Native support allowing for Android, iOS, macOS, Server, Web, and Windows platform support
- A simple command line interface built on Gulp built to help throughout the project’s lifetime (e.g
gulp enable ios,
gulp run android, or
gulp build web --release). Easy to extend by adding Gulp tasks (hint: add your own deployment as tasks).
- Platforms and some features are off by default. Easy to enable with
gulp enable <recipe>.
- Basic app skeleton in place and organized well to grow with the app (includes native cross-platform navigation logic via
react-navigation, and persistent state through
- Internationalization support
And great web-specific features that modern web apps need:
- Progressive Web App enabled including offline support and lighthouse testing
- Code optimizations like Webpack 2 tree shaking (dead code elimination), react class inlining, and optimize-js to reduce start-up times (for most apps). It’s easy to add other optimizations you may prefer.
- Great dev experience through hot module reloading (native-only) and a ready-to-use server for server-side rendering.
Wish list and Goals
Some features, like app updates that bypass the app stores, are easy to implement and project specific. These tools and plugins should be added by hand per-project, and never included in the boilerplate.
This boilerplate is most mature for Web and Android. It would be nice to have the Windows, iOS, and macOS platforms get the same love and treatment. Windows is the newest “official” React Native platform, and the macOS project mentions that there has yet to be a “success” story of an app built on the tech, so building real-world apps on those platforms should be considered new ground and taken with caution.
For Android, more optimization could be built-in well such as code signing and zip aligning, Proguard and Redex optimization and obfuscation, and practical tips on avoiding crashes across the dizzying array of Android devices.
If Ahead of Time compilation is applicable and ever comes to React it would be great to reap those benefits in React projects. I’m unfamiliar with this feature, but I may do some experiments with echo-js to see if it could be helpful in enabling this feature for React.
The final boilerplate makes great progress on my key goals. It’s easy to start a project and customize its platforms and features. I don’t have to remember precisely how every platform works to build and run the project. And the code is organized and standardized so that it’s more likely to last.
It was a blast and a challenge getting everything to click together to create this. This boilerplate contains years of experience mostly in web and Android, so it’s designed to avoid costly problems. Check it out and let me know what you think!
Charlie Hulcher is Co-founder and CTO at UpChannel, where we’re helping phone manufacturers provide first-class experiences to their customers.