LiveView Native is a Browser

An AI-generated image representing web browsers.
Brian Cardarella

CEO & Founder

Brian Cardarella

Build your mobile app more efficiently with LiveView Native. Book a free consult today to learn how we can put it to work for you.

In another post, I took some time to describe how the LiveView Native clients are not WebViews. We do not render HTML/CSS or use a JS bridge to communicate into the device’s native runtime. I went over how we are reconstructing actual native view trees at runtime using native UI components.

Just when you thought you understood how LiveView Native works, I’m going to really confuse you by saying that while LVN is not a WebView: it is a browser. Let’s dive in so you can better understand what this means.

For our purposes, we’re going to define a “browser” as a set of responsibilities along with format-specific implementations. Here are the primary responsibilities of a browser:

  • fetch response from a specified URL
  • parse resulting markup for additional assets to download
  • async download additional assets such as style sheets, scripts, images, fonts, etc…
  • coordinate the construction of view tree (DOM)
  • handle events triggered on the view tree
  • manage network connections
  • manage cookie jar
  • manage asset caching

Nothing listed above says “WebView” or has any requirements on HTML or CSS. These are the core functions that we are defining as the “browser” that we are replicating in the LiveView Native clients. To better understand this let’s roll back to when we were much earlier along in the R&D phase of LiveView Native.

What is LiveView Native, Actually?

Over the years we have been faced with having to answer this question several times: what is LiveView Native?

When we first started out the idea was simple: it was LiveView rendering native UI. The value of LVN would be writing (most) state management and event handling code once for HTML, SwiftUI, JetPack, Windows, etc… then just add a template for whatever platform you want. However, some of our solutions on how to make this all work led us astray at times.

While I had the idea in my head of what I wanted LVN to be, articulating that at times was difficult because I hadn’t yet come to the realization that the LiveView Native clients should just be browsers. This became clear when we started to implement phx.gen.auth. For older versions of LVN we had used things like auth tokens, storing some state in memory on device, and I started to play around with the idea of implementing a key/value store similar to localStorage. If we wanted to support Phoenix’s own generated auth solution, none of these would work. But what if we could just work the way Phoenix expected the client to behave? All we had to do was permit the client’s cookie jar to persist.

Then came the problem of styling the native applications. We tried a few methods; one of them went so far as to re-write every single SwiftUI modifier in Elixir. This meant a huge API surface to maintain. Not to mention the rendering was really slow. Ultimately, the solution was to pre-compile our styling rules into a static asset that can be read at boot-time of the application, instantiated once, and applied to views that need them. Just like how a browser applies styles.

We had already built our markup, and we knew that just like how LiveView does not advocate for 100% server-side rendering we were making the same recommendation. If you need to do something in the client’s native language, go for it.

The more I leaned into thinking the clients were just browsers the more everything else started to fall into place. We implemented similar asset caching strategies, If you disconnect and reconnect, or navigate between live sessions (which does cause a disconnect/reconnect) why incur the network cost of re-downloading a stylesheet you already have downloaded? It may seem like a pretty obvious feature but sometimes it is difficult to see the forest through the trees and I was in the deep wood for three years.

It’s Not a WebView, but It Is a Browser

If we follow the above line of thinking, we can extend these concepts to nearly any UI framework:

Format Markup Styling Runtime ViewTree
HTML HTML CSS JavaScript DOM
SwiftUI SwiftUI Markup Modifier Rules Swift SwiftUI ViewTree
Jetpack Compose Compose Markup Style and Modifier Rules Kotlin Compose ViewTree
WinUI 3 XAML XAML Attributes .NET No ViewTree

As you can see we can extend this concept to any UI framework. I’m hoping that as this proves itself it will enable others to build their own LVN clients.

We took the long road on this one, but I’m very happy with where the project is at. We could have cut corners and just done a WebView that gave native-like experiences. Half measures were never our goal with LiveView Native. It was full native UI or bust. We want LiveView Native to be able to go toe-to-toe with any other native application framework and add to the very impressive set of libraries that exist in Elixir.

Newsletter

Stay in the Know

Get the latest news and insights on Elixir, Phoenix, machine learning, product strategy, and more—delivered straight to your inbox.

Narwin holding a press release sheet while opening the DockYard brand kit box