Local-First Development and Multi-Page Web Apps

Two articles connected in my brain yesterday, so I wrote a little about them.

I saw two articles yesterday that seemed to balance each other well.

The first, “Some Notes on Local-First Development" by Kyle Mathews (h/t Simon Willison), gives a current-state-of-things for a web application architecture where (as I understand it) the data is read and written locally and then synced with a remote database in the background.

The advantages listed are

  • Simplified state management for developers
  • Built-in support for real-time sync, offline usage, and multiplayer collaborative features
  • Faster (60 FPS) CRUD
  • More robust applications for end-users

I found the idea interesting and reminded me of how our team had once architected a native app to read data from a local database first, and the local database is synced to the remote data source in the background. For native, it felt like a very natural architecture since the expectations are that the app works even without a data connection. Applying this same idea to web applications makes sense.

But then I thought about the cost of the additional client-side code for this.

Later, I saw Jeremy Keith’s “Multi-Page Web Apps” where he argues that “multi-page apps” should be the default and single-page apps the exception, and it felt like a little confirmation that, yes, it is worthwhile considering the burden we put on JavaScript to handle more responsibilities.

Then you’ve got to ship all that code to the user before they can use your site. It might be JavaScript code you’ve written yourself or it might be a third-party library designed for building single-page apps. Either way, the user pays a download tax (and a parsing tax, and an execution tax). Whereas with links and forms, all of that functionality is pre-bundled into the user’s web browser.

Admittedly, data access is not an inherent part of browser functionality, but the download/parsing/execution tax is not trivial.

But then Jeremy wisely caveats use cases for single-page apps:

Like I said, there are times when a single-page approach makes sense—it all comes down to whether state needs to be constantly preserved. But these use cases are the exceptions, not the rule.

So what are the use cases for local-first development? I would think it’s for applications where offline use is crucial or where low-latency data access is critical for success. Kyle gives some guidance at the end of his article:

But in general, I’d still be wary of using local-first outside real-time / multiplayer / offline use cases. Local-first is definitely still bleeding-edge. You will hit unexpected problems. A good community has rapidly developed, but there’ll still be some stretches on the road where you’ll have to solve novel problems.

So real-time, multiplayer, and offline are the scenarios he encourages to consider a local-first approach.

I think local-first is certainly a strategy to keep as an option when the circumstances require it, but not the default. Frameworks aiming to solve this piece are exciting to see and will make it an easier solution to implement when the right time comes.