Why I Gave Up On Hybrid Apps
I love developing for the web. The development cycle is fast-paced, I feel confident in the things I produce, and I’ve internalized the patterns and structures enough that I feel positioned to push their boundaries.
In less exciting terms, I’m very comfortable as a web developer.
So when our pivot involved transitioning (and this is skipping quite a few important details for the sake of dramatic effect) from a real estate web app to a mobile video-sharing app, you can imagine that the developer part of my title was not too thrilled.
App development was something completely foreign, something that I enjoyed deferring with a hand-wave and some mutterings about how it was unnecessary and that a well-designed mobile site would do the job just fine.
But now here I was, making a video-sharing app.
As a bit of context, the idea behind Beet is that users tell stories by filming short, candid video clips and these clips create an ongoing montage of their life. They also have the ability to add their clips to larger, community-generated stories based around locations and hashtags.
My first order of business was to find and exploit the most enticing loophole available to me: the hybrid app.
And it was a beautiful loophole. Normal and familiar HTML and JS passing messages to a few necessary native controls. I could just use a few <video> tags and not have to worry about caching or preloading or drawing views or any of that.
Hell, I didn’t even really bother learning how a lot of that worked. I didn’t need to. Like I said, it was beautiful.
And not just from a learning-new-technology standpoint. I was riding the dream that once we were happy with the iOS version, the Android version would be a breeze. It would the same codebase, after all.
I went from having never developed an app before to having a fully functioning social video app on the iOS App Store in just 6 weeks. All with one foot still very firmly cemented in the familiarity of frontend webdev.
It was, quite literally, a react.js app wrapped up in a webview. And it functioned well enough.
But it just didn’t feel right.
Drawing was choppy. Control response sometimes felt weird. Scrolling and gestures were prone to lag.
But the biggest thing was video playback. It was slow to the point of regular failure on anything that wasn’t Wifi or 4G, and forcing inline HTML5 video playback in a webview is something that WKWebView/UIWebView are really not too excited to be doing.
The idea was getting traction, but for a video app, it did a really average job of playing video.
It did a really average job of most things.
At this point, as we were coming up with new features and refining old ones, I made the concession that the hybrid app wasn’t going to cut it.
It might work for a more informational app, or a more utilitarian one. But trying to create an engaging experience around social video just wasn’t going to happen.
So I buckled down and spent two weeks rewriting the entire thing in native Swift. No more webviews, no more hacks.
The animations were beautiful, the transitions and playback were smooth. Preloading and caching made the app feel significantly more responsive than the previous, hybrid version.
It took a little while to get really up to speed with the native way of doing things, but as a result I’m much more confident in the work I’m now putting out, and I think it really shows in the finished product.
I don’t want to say there isn’t a place for hybrid apps; nor do I want to dismiss them entirely. I think they definitely have their place, and there are a lot of exciting things being done with the idea.
But I’ve realized that my place, while I’m on the clock, is not within those experiments. Building a native product might be a harder sell in terms of objective pros and cons, but overall I’ve realized that I’m not in a position to give a shit. I was using the idea of a “hybrid app” as an excuse, not an advancement. Writing native has allowed me to come to a more intimate understanding of the platform and it’s capabilities. Not having to spend time finding workarounds and tracking down weird bugs behind various abstractions is what has allowed me to focus on writing code and shipping products.