When the 8fit team started giving their first steps they decided that the product was going to be a web app with some kind of native integrations. It was something with a lot of sense if we think that the founders of the company feel very comfortable with the language and with web in general. Might we have a great mobile experience using web technologies?
There’s no web solution that equals the mobile native experience. That’s the answer but the truth is that web is getting closer to native and it’s possible (depending on your web stack) to export to native only those components that you need and have a communication interface between the web and the native world, implemented on your own, without Phonegap and some other frameworks that try to abstract the web developer from the mobile layer.
After being working with that solution for months we have figured out that it offers some advantages when you are working with an early product. Some of them are:
Automatic updated without having to pass through a release review: The resources are cached by the local Webview and every time we change the frontend version we don’t have to generate a new build, update the assets, add a Changelog, wait until you get reviewed by Apple and then have another one prepared to send it again to the Apple Store. Forget about that, you can just use a Gulp task that randomizes your resources naming. That way the caching engine of the mobile browser detects that those files have changend and then it reloads them. Updates on the air!
One frontend version but customized for each system: The application logic is the same. What changes then between Android and iOS? Basically the navigation (Android users are adapted to some patterns that iOS users are not and viceversa) and the design. If you organize your frontend following the pattern MVC you can have the same model-controller for both iOS and Android and work change only the View (Layout) and Navigation. At the end if you work natively you talk with your Android/iOS friends and you figure out that they are implementing the same, following a similar structure, and in some cases even the same naming!
Building the web stack
Here’s a summary of things we’re using for the frontend:
- Backbone, Marionette, Underscore & JQuery
- Jade for template
- Gulp for build tasks
- Capistrano for deploys
Note: For those who might be interested in, we’re using Rails for the backend
We rejected any kind of mobile wrapper like Phonegap, Sencha or similars because we wanted custom communication plugins and we had a mobile developer to take care of that side. If you think about it, to have your web solution running on a mobile device (besides having done it responsive) you need a simple app project for Android and iOS (which you can create from the IDE assistant), add a webview, and load the URL into it. Simple really?
That would be the simplest integration but we weren’t a website, we were a platform which purpose was end up running on mobile devices taking advantage of mobile features. How many times do you complain when you have to introduce your credit card numbers for a payment? In app purchases is a great solution there for mobile, or why do you have to introduce your Facebook credentials for login if I have an app installed for that? Those are just some kind of integrations that we thought about and that we currently have.
If you are planning to load a web into a mobile app the app behaves just as a simple window where you show the browser opening your website but if you want to take advantage of the real mobile advantages you need a kind of interaction between mobile-web
That interaction is what we called native bridge and we built it from scratch. No framework, no abstraction, just analyzed the features we had on Android and iOS and then implemented it.
Bridging native and web depends on the platform where we’re building the bridge because Apple and Google had different thoughts about giving support to web when they developed their mobile web engines.
Where we can see we’re exposing a method called
If we tried to close the payment flow, the exchange of calls would be something like:
Which is a method to ask if the webview should or not load a given
Let’s say that we built a custom communication API using the scheme
eightfit:// and that way any intercepted url with the scheme
eightfit:// would be passed to the NativeBridge. The previos
buyIAPProduct would turn into
The parsing of the URL can be made using regex but fortunately there were other developers thinking about it befure and we find libraries like JLRoutes which helps on that. What JLRoutes actually does is to build a local API passing the endpoints and actions for those endpoints:
Some points about the bridge
As you might have noticed there are some interesting points to comment about the bridge. The first one is that the communication is a bidirectional communication. I ask for something you answer with another thing. There’s no way (right now) to get the return parameter of the sentence evaluation and if there’s a way it’s only using the string type, (what if I want to return a more complex object?)
Exposing features: If you want to let your frontend know about the available mobile features, the device or the app version you can use the User-Agent and do something like: 8fit-iOS-8.1/iPhone-6/1.2.3 (iap, push, conn, res) . That way your frontend knows about what is available and what’s not.
Examples of controllers
Since we starting building that bridge we’ve done more than 10 kind of native integrations. Some of them are payments (in app purchase), video/sound/audio player, push notifications, login with Facebook, resources downloader, social sharing…
And some other interesting are coming. We’re working on a frontend controller which is going to manage the frontend locally and inject it into the webview. We’re finishing the integration with HealthKit and Google Fit and planning to do the workouts more interactive implementing them natively.
Pitfalls and recommendations
Not everything can be magic, there are some pitfalls we found during the development of 8fit and that I would like to share with you too because you’ll have to face with them sooner or later:
- Need a bit of mobile knowledge : If you come from web you can learn it, the complexity will depend on the number of native integrations you have. If they are not too much give your first steps on mobile, otherwise Phonegap is not a bad solution but not too custom for us.
- Experience close to mobile but not the same: We can start a big discussion here but my opinion about that is that there’s no way (right now) to get the sdame experience than a native app using web technologies. Due (in part) to the companies behind the OS (Google & Apple) which don’t want to put their efforts on better web rendering engines. Fortunately, I’ve to say that the things and changes and we can see great news on iOS 8 and Lollipop
- Test the mobile experience: This point is not taken a lot into account on a desktop solution but should be in case of mobile. Think about what should happens if your apps loses the connection, are the models properly persisted under wrong connection health, … Check if the browser handles properly the cached resources.
- Be careful with the cache: We had some troubles with the browser not reloading cached resources. To avoid that we started renaming the frontend resources on every build, that way the browser detected them as updated and forced the download of them. Note: We’re building here our current frontend controller which is going to be the repsonsible to download it and inject into the Webview! Yei!
After the previous (and big summary) of the technologies we’re using at 8fit and different topics around it I would like to finish the post sharing some conclusions with you, the slides and the video of the talk given at @Geekshubs
- It might be restrictive in the future in terms of interactivity, animations, … If you start noticing that, you can remove those bottlenecks using a native solution for them. We’re doing though with the interactive workouts.
- Analyze your resources and your product If you have enough resources to have a mobile solution do it! But if now let’s make web dancing on mobile we did it!