Native or Hybrid – The Path of Least Resistance

When building an app in this day and age, the common question most people ask is, “Are going to build a purely native application with Objective-C/Swift for iOS and Java for Android, or you going to go the hybrid route?” A couple of years ago, most developers felt that the only way to go for the top performance level was native, but with the new browsers, devices and platforms that have been coming out, I believe that the decision has become more and more favorable to Hybrid.

If you’d like to learn more about what a hybrid app is, read John Bristowe’s article on the topic.

Untappd

We first built Untappd as mobile-web only application back in early 2010. Untappd is a social beer network that allows users to rate, review and share beers they are having with friends. At that time, the options were pretty much “native only” when developing mobile applications, but, due to our limited native development skills, we wanted to test the waters out by using the mobile web.

It worked to our advantage because it allowed everyone with a phone to get our platform on day one, instead of waiting for a specific platform version for that device. This helped us gain traction and users without investing heavily in a particular platform.

As we grew, we realized that we wanted to make the jump to the app store because we believed that, as users discover apps, they discover them through native stores and the concept of “web-app” did not resonate well with users in terms of signing up and using the service. When deciding if we should “bite the bullet” and go straight native or look into hybrid solutions – we took these three key topics and attempted to expand on them before making a decision.

Ease of Development

Being a small, two-man operation, the thought of building just an iOS project was pretty daunting. We already had a full desktop web product and a mobile web version – managing two code bases was hard enough with only one engineer (myself).

We wanted to develop a solution where we could reuse some of the JavaScript, CSS and HTML that we’d already written for the mobile web and desktop version of Untappd – to be formatted toward a mobile hybrid solution. This would easily allow us to iterate often our product and push features to all phones simply, without staggering releases across platforms. Hybrid won this key point because of it’s ease of development and allowed us to use our own skills as web developers to build, maintain and scale our apps using our knowledge and reusing code across platforms.

For example, if we wanted to add a tab bar for our iOS and Android app – we simply copied over the code from mobile web version and placed in our Cordova project. The best thing is that we could tweak it and test it in the browser before being part of a build process for the the native applications.

For our project, this is exactly what we did, as the code below was used in our mobile web version as well as our apps to create a seemless experience. In most cases, we wanted to build a different presentation on each OS to cater toward their UI and UX standards. While we did create different markup for Android and iOS, we were able to reuse the code and just place it in our app. In our testing and development, this was much easier than the alternative of having the build these elements from scratch on every platform.

Android:

<div id="tab_bar" class="hide">
  <nav id="tab_bar_nav">
    <a href="#"" class="active tab_pub tab_btn"><p>The Pub</p></a>
    <a href="#" class="tab_discover tab_btn"><p>Discover</p></a>
    <a href="#" class="tab_friends tab_btn"><p id="pendingFriendsNotice">Friends</p></a>
    <a href="#" class="tab_yourtab tab_btn"><p>Your Area</p></a>
    <a href="#" class="tab_notices tab_btn"><p>Notices</p></a>
    <div id="notify-popup" style="display: none;">
      <ul>
        <li class="toasts" style=""><span></span></li>
        <li class="comments" style=""><span></span></li>
        <li class="news" style=""><span></span></li>
      </ul>
    </div>
  </nav>
</div>

code_reuse_android

iOS:

<div id="tab_bar" class="hide">
    <nav id="tab_bar_nav">
      <a href="#" class="active tab_pub tab_btn button">
        <p><span>The Pub</span></p>
      </a>
      <a href="#" class="tab_discover button tab_btn">
        <p><span>Discover</span></p>
      </a>
      <a href="#" class="tab_drinkup button tab_btn">
        <p><span>Drink Up</span></p>
      </a>
      <a href="#" class="tab_yourtab button tab_btn">
        <p><span>Profile</span></p>
      </a>
      <a href="#" class="tab_notices button tab_btn">
        <p><span>Notices</span></p>
      </a>
      <div id="notify-popup" class="hide">
        <ul>
          <li class="toasts" style=""><span>14</span></li>
          <li class="comments" style=""><span>1</span></li>
          <li class="news" style=""><span>15</span></li>
        </ul>
      </div>
    </nav>
</div>

code_reuse_ios

Performance, Performance and Performance

We are currently using Phonegap (the Cordova project) to power all of our native apps for iOS, Android and Windows Phone. When we were considering using Cordova, all we heard from other developers were things like, “The WebView lags in performance,” and, “It’s really easy to tell between an hybrid app and an native one.”

One thing we learned pretty quickly is that users don’t really care what the app was built in – they just want it to be fast, accessible and fun to use. A lot of developers pay too much attention to the performance hit between WebView and Native and how the users will perceive that difference. While there are always going to be some users that may notice, my experience is that a majority of our user base don’t really care.

Users also want the app to work when they want it, wherever they want it. With that said – we wanted to use our web development skills again to see if we could prototype a solution with HTML5, CSS, and JavaScript to make a really fast hybrid app.

For example, we originally had a complex list view with box shadow around every element on the page (the avatar, the box, the text, etc). While it looked awesome, it caused very poor performance. To help render those elements faster – we dropped multiple Box Shadows, and added webkit-transform to the scrollable area. It worked like magic to improve rendering and force the browser to have the GPU of the device render these, instead of the browser.

You can add this to your app like so:

.list-container {
    -webkit-transform: translate3d(0,0,0);
    -webkit-backface-visibility: hidden;
}

Be careful not to add these to each item in your list, as on older devices it may cause crashes of the WebView due to memory issues. By applying this CSS to the parent element, it will cascade to the others in the list.

Speaking of memory, when developing for desktop web sites, a developer doesn’t really have to worry about memory usage and reflows. For mobile devices, however, it becomes a large battle.

Being smart with your DOM structure will make your hybrid app way more performant than you ever thought possible. You can’t simply just take your mobile web and wrap it in to WebView – you need to make some tweaks so it looks and feel native. That can help the user experience, and allow the user to enjoy the app.

For example, if you have a list of items, you may have built it up and put tons of <div> elements inside each list item. But, by minimizing the DOM elements inside a scrollable list, you can decrease reflow and performance. The leaner your markup is, the faster it will run inside the webview.

<ul>
    <li>
        <a href="#">
            ...
            <!-- content here -->
        </a>
    </li>
</ul>

Extensibility and User Experience

Building for the mobile web and native are two entirely different experiences. On the mobile web, you may not have to worry about offline access or native gestures. With native apps, users expect your app to work, look and feel like their other apps.

For us, we loved the extensibility of Cordova Plugins such as those found on the Telerik Plugin Marketplace. These plugins provide developers with a great range of tools to allow their JavaScript code to directly connect with native code.

For example, we use the ActionSheet plugin on Android, iOS and Windows Phone to show native option menus for secondary actions:

screenshot1

To use the ActionSheet Plugin, all we had to do (after adding it to our Cordova project), was to call it, as shown below. It’s really simple and easy to use. The best part is this code can replicate across platforms. No more having to write the same logic more than once!

var options = {
    "title": "My Title",
    "buttonLabels": ["Button 1", "Button 2"],
    "addCancelButtonWithLabel": "Cancel"
}

window.plugins.actionsheet.show(options, sucessCallBack;

Using plugins and leveraging native controls helps improve the user experience with the app and make it “feel native”, but also gives the developer an opportunity to use standard UI elements that they are familiar with.

Conclusion

When it comes down to deciding if Native or Hybrid is right for you, it depends on your use-case. For us, being a small team, sharing code and high performance was key to helping us make a successful app with the hybrid approach. To us, this was the right decision, as it allowed us to scale to all major platforms with only 1 engineer and 1 designer. We can update our code in one place and then generate native apps with minimal additional effort, which helps us get new features out users faster without spending too much time on development.

Header image courtesy of Cyril Caton

Comments