What I think the single-page app era got right and wrong

The concrete National Library of Argentina in Buenos Aires, a brutalist block raised on four thick legs above a plaza

I spent a good part of my career building single-page applications (SPAs), the kind where the browser loads one page and the JavaScript takes it from there. I would build some of them again. Not all of them. Here is what I think the era got right, what it got wrong, and what I carry forward.

What it got right

The component model. Before SPAs, interface code was organized by page, and the same widget was built three times in three places. The idea that an interface is composed from reusable parts, each owning its own markup, behavior, and style, is the single best thing to come out of the era, and it has outlived the frameworks that introduced it.

The interface as a function of state. Rendering from data instead of mutating the page by hand removed an entire class of bugs where the screen and the data disagreed. Anyone who maintained a large jQuery application knows what that class of bugs cost.

A real build pipeline for the front end. Linting, type checking, tests, and bundling on every change were server-side practices that front-end code did not get until SPAs made them necessary. They stayed, and they should.

What it got wrong

The default. For about a decade the answer to what kind of app should this be was an SPA, before the question was asked. Marketing pages became SPAs. Documentation became SPAs. Forms that posted one thing became SPAs. Each one shipped a large bundle, rebuilt routing the browser already had, and reimplemented the back button, often badly.

I think the honest accounting is that most of those should have been pages. A document wants to be a document: fast to load, easy to link, indexable, working before any script runs. The SPA model was right for the application-shaped things, the dashboards and editors and tools where state is complex and lives for a long session. It was wrong for the content-shaped things, and we built it there anyway because the tooling was fun and the team knew it.

Client-side state was the other place it went wrong. Once the browser owned the state, the browser had to fetch it, cache it, keep it fresh, and reconcile it with the server, which is the work a server had been doing for twenty years. Much of the complexity people associate with front-end development is that work, moved to the harder side of the network.

What I carry forward

Today I ask what shape the thing is before I ask what framework to use. If it is content, it is pages, rendered on the server, with script added where a page needs behavior. If it is an application, it is an application, with a client-side model and the discipline that comes with it. Most products are both, and the current generation of frameworks is finally comfortable saying so, rendering on the server by default and hydrating only the parts that need to be alive.

The component model comes along either way. The build pipeline comes along either way. What I leave behind is the assumption that everything is an app, and the state management that assumption required.

I do not think the SPA era was a mistake. I think it was a generation of engineers discovering how much the browser could do, and then discovering, more slowly, how much of it we should have let the server keep.

Photo source: https://photos.robertstowe.com/buenos-aires