Talks

Native Apps are Dead, Long Live Native Apps

Native apps are dead, long live native apps: Using Turbo Native to make hybrid apps that don’t suck

wroc_love.rb 2023

00:00:11.219 Thank you for being here. Today, I'm going to talk about Turbo Native, so let's quickly cover what to expect in this presentation. First, we'll define what a hybrid app actually is to ensure we are all on the same page regarding hybrid technology.
00:00:25.140 Next, we'll discuss how hybrid apps have gotten such a bad reputation in the tech industry. For some reason, it seems like the tech industry has a negative bias against hybrid apps, and we’ll explore why that might be inaccurate.
00:00:36.360 Then, we'll take a closer look at what Turbo Native is, returning to the basics and evaluating how to get hybrid apps right. They have a poor reputation for a reason, and there are certainly wrong ways to do it, which we will go over.
00:00:53.520 But before we dive in, let me introduce myself. My name is Ayush, and I live in London. Here's a little avatar of mine from my social profiles, although I’m not quite that rock and roll in reality. I might exaggerate a bit online. I was a mobile developer for five years before transitioning to Ruby and Rails in 2020. Now, I’m a freelancer mostly focused on building websites with Ruby on Rails.
00:01:13.619 Apart from that, I co-host a podcast called 'Justice Spec' with my friend Jared. It's about the projects, people, and protocols that make the open standards of the internet possible. Also, I’m on the core team of a progressive site generator called Bridgetown, which started as a fork of Jekyll but has evolved into something unique. If you’re a bit fed up with Jekyll, I highly recommend checking out Bridgetown.
00:01:50.159 Additionally, I run a small indie web app called Scattergun, a privacy-focused mailing list platform, though everything is kind of on pause right now. Finally, I recently published a book that some of you may have seen flyers for. Interestingly, I realized on my way to the party last night that I opened pre-orders for it exactly one year ago. It’s a bit of a milestone for me.
00:02:07.140 I believe it's one of the most comprehensive resources on Rails and Hotwire, so if you’re interested in those topics, please check it out. Anyway, enough about me. Let’s define what a hybrid app is. A hybrid app combines web technologies like HTML, CSS, and JavaScript with native APIs. How these two worlds collide depends on the tools you use.
00:02:40.800 Some mainstream tools for hybrid apps include Cordova, formerly known as PhoneGap, and React Native. These are the tools people typically associate with hybrid apps, and we'll discuss them further in a bit.
00:02:58.560 Now, let’s take a rather sizable detour into a story about a monastery in ancient China. Once, a distinguished Taoist guru lived there with his disciples. Every evening, the monks gathered in the Great Hall to listen to their leader’s teachings and meditate. However, a cat had adopted this monastery as its home, and every evening, it would follow the monks into the Great Hall, causing distractions during their silent meditation.
00:03:56.040 Eventually, the teacher got so fed up that he told the monks to put a collar on the cat and tether it to the far side of the monastery to prevent interruptions. This worked for a while. The teacher, the monks, and the cat followed their nightly routines without issues until one day, the teacher passed away. Yet, the monks continued to tie the cat up every evening until the cat died as well. They even went to the nearest village and bought a replacement cat, continuing the practice of tethering it every evening.
00:04:54.919 Centuries later, religious scholars wrote learned essays on the importance of tying up a cat prior to evening meditation. This story is called 'The Tale of the Tethered Cat', and it serves to explain principles that have outlived the conditions that created them.
00:05:07.439 Tech loves a tethered cat, and this resonates with me. However, I can’t help but think that the belief that hybrid apps are bad is another tethered cat. Over the years, I’ve heard so many opinions about hybrid apps—how they are slow, don’t look native, or are insecure. How did these beliefs become so ingrained in the industry?
00:05:43.620 I have a theory that traces back to Mark Zuckerberg's quote from 2012, where he said that the biggest mistake Facebook made was betting on HTML5 over native. If Lord Zuckerberg claims it, it must be true, right? Facebook did rewrite its HTML app using fully native tech and highlighted that fact, which laid the groundwork for the ongoing myth that hybrid apps are inferior.
00:06:01.560 Another contributing factor involves the tools I mentioned earlier—Cordova and React Native. Both rely on one philosophy: sharing a single code base between platforms. This concept has never worked effectively. Does anyone remember Java apps? They didn’t age well either. And when was the last time you encountered a truly delightful Electron app? You can't truly share one code base and expect it to work seamlessly across platforms.
00:06:32.280 On top of that, Cordova builds your app’s UI entirely in HTML, CSS, and JavaScript. iOS and Android have their own design standards, making it impossible to create a single UI standard that feels familiar and native to users. Instead, it ends up feeling like a website in a box, which leads to a poor user experience. That's why I don't consider Cordova a suitable option. As for React Native, I won’t rant about it—less is more in this case. Instead, I’ll share what the former lead developer, who worked on React Native, had in his Twitter bio: "Partly to blame for React Native." That says so much.
00:07:27.180 Let’s agree that these tools aren’t great. Between these tools and Zuckerberg’s quote from 2012, we have a textbook example of a tethered cat. Before we explore why these assumptions may not be valid in 2023, let’s detour into the English countryside.
00:08:02.100 In this quaint setting, there was a man who had to walk a long way to work every day. He was forced to take a longer route because of a hedge blocking the direct path. This added significant time to his daily commute. Frustrated, he finally decided to make a hole in the hedge to walk the more direct route. On that fateful day, a bull that lived on the other side of the hedge charged at him and met his demise.
00:08:56.760 This story comes from British philosopher GK Chesterton and is called 'Chesterton’s Fence'. It explains that we shouldn’t remove a rule without fully understanding why it was established and the effects its presence has. This serves as a great counterpoint to the tethered cat analogy; we shouldn’t just disregard rules without understanding their origins.
00:09:35.720 Let's examine why the belief that hybrid apps are bad took root. Zuckerberg’s statement comes from 2012—a full 11 years ago. At that time, the mobile JavaScript performance landscape was drastically different. I found an old iPhone 6 in my drawer and ran a speedometer test, which scored 24.8. This performance was still better than the tech environment when Zuckerberg made his comment.
00:10:11.260 Next, I ran the test on my current phone, an iPhone 13 mini, which scored much higher. This remarkable leap in performance over just a decade is staggering. Granted, we’re looking at high-end models, but it's clear there has been substantial growth in mobile JavaScript performance since 2012. Anecdotally, when I asked friends with Android devices to run this test, results ranged from 60 to 100, indicating a 3X improvement since 2014.
00:10:53.460 I think it's clear that the current landscape is significantly different from when hybrid apps earned their bad reputation. This is an opportunity to reassess that approach. So when should we opt for hybrid? Of course, they're not a silver bullet and won’t fit every scenario. Hybrid apps work best when your app's core is a server-rendered web application using HTML, CSS, and JavaScript.
00:11:21.240 If you're developing something like Uber, which requires deep native integration and might not even need a web app, that's when fully native is the way to go. Thus, deciding to go hybrid or native hinges on the use case.
00:11:52.760 So why should we consider a hybrid approach? The primary advantage is the ability to reuse all your views from the web app. Since you build with web technologies, you can leverage your HTML, CSS, and JavaScript. However, if you go fully native, you must recreate every screen for both platforms—this can be immensely challenging or even impossible for small teams.
00:12:27.059 Reusing views provides a significant competitive edge because you maintain one foot in native territory. You can still utilize our native APIs for notifications, maps, contacts—everything that defines an app, essentially. This hybrid model lets you have the best of both worlds, to a point.
00:13:01.740 Additionally, you can deploy updates remotely from the web app. There are limits to what you can accomplish, but once your native code reaches a certain stability level, you can push significant changes with just a server deploy. As of now, this method remains compliant under App Store regulations, although it’s uncertain how long that will last. It's a considerable advantage.
00:13:57.240 Now, let’s discuss a better approach to building hybrid apps. The key is to maintain separate code bases for iOS and Android, as sharing one code base typically leads to issues.
00:14:05.940 Build a native app backbone using fully native tech, like Xcode for iOS and Android Studio for Android, along with Swift and Kotlin. This backbone can effectively manage the navigation bar and tab bar, adhering to native UI standards.
00:14:37.140 The actual content of the screen is rendered in a web view that displays HTML content. This way, your app operates like a custom web browser, providing a fully native experience while still incorporating web content.
00:15:03.480 The real advantage of this approach is that users receive all the expected native behaviors, such as smooth screen transitions and intuitive swipe navigation, because the navigation and structural components are fully native. Turbo Native enhances this experience.
00:15:44.780 Turbo Native is part of the Hotwire suite of open-source front-end tools created by 37signals. This suite includes Turbo, which is a JavaScript library, and it’s extended by Turbo Native. Another component of this suite is Stimulus, a JavaScript library that facilitates attaching pieces of JavaScript logic in the form of controllers to HTML elements. There's also a third part called Strata, which has yet to be released but is expected to enhance Turbo Native in some way.
00:16:30.800 Now, Turbo Native is a native library for Android written in Kotlin and Swift for iOS. While conceptually, the libraries work similarly across platforms, the code implementation uses platform-specific design patterns, reinforcing the idea that a shared code base between platforms does not function effectively.
00:17:16.739 Turbo interacts with Turbo Drive, which is pivotal to how Turbo Native operates. Turbo Drive, on the web, intercepts link clicks with JavaScript to make fetch requests to their destinations, replacing the body element with the response while updating the URL using the push state API. These interactions boost performance as the app does not need to reload and parse all JavaScript and stylesheets again.
00:18:03.679 For Turbo Native, when a web page loads, Turbo installs itself as an adapter in the web view. It does this through the native APIs available in both iOS and Android for communicating with JavaScript, allowing for a two-way communication pathway.
00:18:41.700 In a Turbo Native app, when a user clicks a link, instead of only issuing a fetch request, a native method is called. This allows you to choose whether to proceed with standard navigation or display a fully native screen. This flexibility permits a gradual integration of native and web components.
00:19:10.560 The default navigation within Turbo Native involves creating a new instance of the native screen with an embedded web view, ultimately utilizing Turbo to navigate the web view to the intended destination. Users experience seamless transitions without realizing the complexity happening behind the scenes.
00:19:52.740 You can reuse the same instance of the web view across the entire app, navigating it using Turbo’s mechanisms. This helps maintain performance advantages of Turbo while ensuring a consistent user experience.
00:20:14.070 Let's look at a demonstration. That looks pretty native to me, as the interface is entirely web content. Also, there's a fully native login button in the corner of the hybrid app.
00:20:54.579 How do we create such a hybrid app while rendering a fully native component? By using the native APIs available in both iOS and Android, we can establish a web-to-native bridge that allows the web app to send messages to native code.
00:21:24.680 This setup facilitates invoking Swift methods with messages sent from JavaScript, enabling developers to manipulate native functionalities in response to web interactions. Corresponding methods exist in both iOS and Android.
00:22:09.120 When we want to send messages from native to web, we simply evaluate JavaScript within the web view using corresponding methods for each platform. This two-way bridge enhances the fidelity of your application, lending it a more authentic native feel.
00:23:00.360 To implement features like the native login button, we create a proxy web element in the native environment that acts as a communication bridge. This element, which is invisible to the user, contains data attributes that inform the native application what action to take.
00:23:41.940 When the proxy element connects to the DOM, we make it invisible to the web interface. A Java class encapsulates the data attributes to streamline the process, particularly regarding platform differentiation when sending messages based on whether the app is running on iOS or Android.
00:24:24.180 We've also developed a web bridge that employs the adapter pattern to route messages to their respective native API endpoints. After serializing the bridge element data to JSON, we send it to the native app to execute the desired action, while simultaneously introducing logic to handle clicks and interactions accurately.
00:25:40.500 One more rewarding aspect of this setup is that, once everything is configured, it allows for a fully native button triggering a link on the web. This presents the ability to pass messages back and forth seamlessly.
00:26:23.620 With this functionality in place, you can develop highly interactive components that encourage user engagement. Additionally, you’re free to create various UI elements—menus, buttons, and tabs—that enhance the overall aesthetics and usability of the web content integrated within your app.
00:27:24.360 Lastly, Strata is in development to add an abstraction layer or standardization to this web-to-native bridge model. As we await more details, it remains an exciting prospect for improving hybrid app development.
00:28:01.060 In conclusion, we must address the burning question: is the experience from Turbo Native on par with that of a fully native app? The answer is no; it simply isn't comparable.
00:28:27.940 However, it is 'good enough' for many use cases. After a certain point, the returns from developing fully native apps diminish, which leads us to question whether the high investment is truly justified.
00:28:54.339 Take note that consumers primarily care about functionality. Whether your app is written in web tech, Swift, Kotlin, or anything else, users are interested in solving their problems efficiently. They won't fuss about the technology behind your app.
00:29:32.280 We can validate this by observing two major players: Basecamp and HEY, both champions of Turbo Native, which consistently receive high app store ratings. An unexpected example is the BBC Sport app, which is hybrid yet boasts an impressive app store rating of 4.7, showing just how effective this approach can be.
00:30:42.459 Any questions?
00:31:21.980 I have a question. Am I correct in saying that if you use this native solution, you would need to create at least part of a code base for iOS and another part for Android?
00:31:37.800 Yes, you would need to write at least some native code, and you would indeed have to maintain an iOS and Android repository. It's worth the investment, as once your app reaches a certain stage, the web can drive most aspects of it.
00:32:00.580 Could you provide some use cases where hybrid wouldn’t be ideal based on your experience?
00:32:45.140 Not from personal experience, but typically when your product isn’t centered around a web app that utilizes HTML, JavaScript, and CSS, hybrid solutions won't be effective. If you lack that web foundation, the hybrid approach doesn't make much sense.
00:33:31.620 Do you have experience in testing these types of apps and creating automated tests for hybrid apps?
00:34:32.980 Unfortunately, I don't.
00:35:04.860 Do you have a scaffold application or generator within Rails that allows rapid deployment for these applications?
00:35:56.200 Currently, there is nothing built into Rails. However, you might want to check Jumpstart Pro, created by Chris Oliver. It provides an app kit for Rails with native starting points that use Turbo Native.
00:36:21.860 What are the licenses for those native libraries used in Turbo Native? Are they open source?
00:36:37.820 Yes, they are open source, under the MIT license.
00:36:47.540 Thank you for your presentation. I'm curious about your experiences with hybrid apps compared to React Native. I found that hybrid approaches didn’t feel as robust while React Native proved more appealing.
00:37:02.500 It's hard to comment precisely since I have limited experience with React Native. The fundamental difference between React Native and hybrid is how they render components—React Native uses JavaScript for a primarily native experience.
00:37:37.360 Hybrid approaches allow for the reuse of web app views, providing an opportunity to ease development efforts while simultaneously offering native functionality. If you’re more focused on functional performance without being abstracted away from the native experience, hybrid apps might suit your needs.
00:38:18.960 Thank you very much!