Architecture no one needs is server side templating

By Toni Petrina

In a blog post named The Architecture No One Needs Greg Navis claims that SPA (Single Page Applications) are “almost always worse than a multi-page app” and claims that there are alternatives that “can yield similar benefits without the costs”. To put it mildly, I disagree with him and I’ll try to explain why I feel SPA are paving the road for the future.

While I agree that not all apps should use SPA model nor should every team embrace developing in a new technology, there is something significantly broken in pretty much all alternatives to SPA approach. Let’s analyse the main problem with building applications “the old way”.

Before SPA frameworks came on the scene almost all apps were developed with using server side languages with templating systems: PHP, Ruby, Python, Java, C#, etc. Applications built this way rarely had complex client side logic or interaction that required writing lots of JavaScript code. This was ok, but let’s see what problems we have in this approach:

  1. Templating language is basically string interpolation which builds the presentational layer at load time.
  2. Client side code is developed separately and has to “pick up” the target elements after it is loaded.

For any large application (by large I mean more than 50 individually developed screens) this slowly becomes harder to maintain. Templating languages are basically smart string interpolators and have quirky syntax. Let’s not forget that some people even generate JavaScript code using templating language just because they can — it is string after all.

Razor/C#

While the image above displays a simple example, it is already clear what kind of problems arise in templating languages. One language (server side) is generating markup for a different language which takes over on the client. Taking over means finding all elements, subscribing to all events and add interactivity. The gap between the original content and the interactivity itself is huge.

If AJAX is used to dynamically alter the state of our app by means of adding, extending or removing the interactivity of some parts, it becomes extremely problematic how we are going to:

  1. Use runtime templating after AJAX call is done. We cannot use server side rendering any more — or can we? Let’s write endpoints that return HTML and not JSON.
  2. When to subscribe/unsubscribe from events. Otherwise we will run into memory leaks.
  3. How to name things — when everything is dynamic, naming becomes hard.
  4. How to develop components in isolation now that on some are generated on server while others are generated on the client. Or style them. Or test them.

Templating only addresses the initial data load — or let’s call it document rendering. Applications are simply not documents, they are what we call interactive software. Once upon a time they were named RIA or Rich Internet Applications, today they are just apps. Taking paradigms that work well for static documents and using them for building software is simply inadequate.

Large applications tend to have certain parts repeated — let’s call them components. Reusing components that should be well defined and isolated across a large number of screens is a real need. Templating systems have support for extracting sub-templates (it is not fair to call them components) but writing client side code that correctly works with said components is hard. That is why writing good components in templating systems is hard.

How easy it is to develop client side code for that component depends on the templating language, but simply “string splitting” across files is not good enough.

Traditionally all platforms came with such components. Desktop and mobile apps are built using frameworks that have components as a first class citizens. After all, basic building blocks for those platforms were built using such approach. It is a little unfortunate that Web never had a platform owner that could develop such framework from the get-go.

Instead we got the frenzy of frameworks and a maddening pace of innovation. Some call it JavaScript fatigue, some call it “reinventing the wheel”. Others call it job security, but I see it as a way forward.

Lastly, building large applications means taking a lot of third-party components and integrating them inside the new application. Most components are built with client in mind (or clients since same app has to work on desktop, tablets and phones), not a particular server technology (let alone your favourite one). Integrating such components, some which may be simple elegant tooltips or progress bars while others may be full-blown kits, doesn’t scale across huge number of server-side templates.

Proper handling of lifecycle methods for such components requires having that thought out before hand on your server side. And that is what we call a frontend framework! So avoiding SPA framework doesn’t help if server side templates have to be aware of the potential problems caused by some client side components.

Let’s be honest — the only way one can say developing SPA application is costly is if they either don’t know any SPA technology or if they don’t want to learn it.

Developing large software with lots of components is simpler in one technology that has interactivity baked in than building it using string interpolation with late binding. Of course there is penalty for “first page load”, but we are building apps, not “pages” or “documents”. And with server side part of some frameworks from the get-go, this isn’t really an argument.

Things that are more expensive to develop in server side rendered applications:

  1. Knowing server side templating language. Also not being able to use the same language for AJAX templating.
  2. If you have proper mobile app, an API has to be developed for that. Having two layers accessing the same data in two different ways is not practical.
  3. Testing components in isolation. Tools like Storybook are unique value proposition of SPAs.
  4. Pretty error handling — instead of serving 500 for a bewildered user, display nice message with an option to track last steps, ask for user input or offer an easy way to retry an action. Do you really want to build apps that display the dreaded “Please do not close this window…” message?
  5. State on the client — because that is where the state belongs to. APIs should be easy to develop, test, deploy and extend without worrying about session state which I consider the bane of server side technologies.

Yes, SPA applications are sometimes large, bloated and load slowly (especially on mobile). But they are the way to go. Not because they are single paged, that was never important, but because they solved the major problems all large applications had solved before: component system on the client.

Even when developing mostly static sites it is quite nice to render SPAs on the server because it is easier to develop using component based systems. Nice example of this is Gatsby — compare its component model for building rich pages with templating systems that are nothing more than string interpolators. Another nice example is BBC News front page — built using server side React.

Code splitting, server side SPA rendering, precompiling views — we take for granted the experience we have developing desktop/mobile apps — it had to be built from scratch for Web. We have those tools because there were no tools! We just got started with the web revolution. Yes, Web Components are coming, but they are far away.

I for one welcome our new SPA overlords.