This often gives the impression that I dislike SPA frameworks in general and telling people that I like such frameworks (and admire the genius behind some of the ideas) if they are used to tackle actual requirements does not get rid of that impression. I’m a big fan of JS and I use it for nearly everything I do, for CLI tools and server-side applications, and of course also in the browser. So why do I attack the “JS-all-the-things” approach so much? In this blog post I try to explain my personal view a little bit and discuss the different cases where it makes sense to use an SPA.
I have tried to avoid such discussions for a while now, mainly because they leave me completely exhausted afterwards. I’m not interested in to telling people to use a certain product so that I or my company can sell our special services for product A or similar. Mainly I’m motivated to help people find durable solutions that also can be developed with an early time-to-market in mind. While durable solutions require things like quality, dependency management, and complexity reduction, early time-to-market is something that needs clear guidelines, concepts and fast tools. In my opinion, the right tools for the latter are often very bad for the former. So if durability is not important, a minimal time-to-market can be the driver for all of your decisions: COTS, SPA Frameworks, Complete Component Sets in Framework X, … Just use what you need :)
When both are important, I want to discuss at least a bit what is needed and what should be used. This discussion is difficult for many Product Developers nowadays since Google and Facebook have already told us what to do, right? If the big ones tell us to “Angular/React all the things!”, why do we even need to think about alternatives?
I personally would not have an issue with the decision to use Angular or React, but it bothers me when I see a lot of people arguing for big SPA frameworks when I don’t really understand why. I like to understand the use cases for the web applications first and then try to use the best fit for the technologies that we decide to use. So why do I come so often to a different conclusion about the most fitting technology? In my opinion it happens because there are two different categories of arguments that appear in such discussions. There are extrinsic requirements, the things your web-site and user experience (including information architecture and such) needs to support, and there are intrinsic requirements that are non-functional in appearance and are driven mainly by the demand of the developers.
Sometimes you clearly need client-side routing. The two main reasons that come to my mind are:
- A lack of a dynamic web-server
- A single window appliance without classical browser navigation
The first is often the case when we have chosen a minimal server stack, e.g. to keep the OPS difficulty very low (a Jamstack might be a good example). The second case could occur, for instance, when you build complex UIs for an IoT Device based on a webview solution. Usually you end up with a single web-view where you want to provide a complex user-navigation likewise to different pages but without having the navigation elements of a classical browser in place.
2-way Data Binding and lots of client-state
If you have many components on a page and they communicate a lot together and changing a single element (e.g. a slider) needs to transform a lot of client-side (often representation-related) state, a big JS framework might really help to manage such complexity. This is often the case when many components are provided that are different representations of the same data and the UI needs to react to changes to that data in an instantaneous manner.
Offline State manipulation for huge amounts of state
If you have use cases where users manipulate data on client-side, maybe even for a longer time, without having to communicate with the server, then we are basically talking about offline-capabilities. In such a use case we often end up with one or more complex data-stores that need to be handled on the client-side and might be synchronised to the backend from time to time. In such a case, you might also want to have a bigger JS framework at hand, that (hopefully) ships some bullet proof concepts on how to handle this efficiently.
Advanced Dom-Diffing for Rendering Performance
A classic use case often showcased by Facebook’s React is being able to update of DOM Elements extremely quickly by using DOM diffing. Use cases for this are usually related to graphical representation of fast changing data sets.
The above list definitely not an exhaustive one, and there are for sure to be more extrinsic use cases that are good arguments for using a big JS framework (or a smaller one like preact or Vue).
The component oriented programming model is for sure one of the stronger arguments that I hear often as a pro-argument for SPA Frameworks. This is especially true when people like the idea of CSS being part of the JS component definition (I do not). This is also strongly requested by “backend”-developers to allow them to abstract JS (and CSS) out of their developer experience. Let’s use Framework X so that it looks like Java or .Net (especially when Typescript is invited to the party)!
Frontend/Backend Split (backend is a Problem of others)
“When we develop the application completely in the frontend, we are not depending on the slow server development teams!” is maybe one of the most frequently cited arguments in such discussions. Sometimes it is explicitly stated and sometimes it is only subtext, but it is almost always there.
Faster Prototyping === Faster Product Development
A strong argument for using React/Angular is often that people are writing (or even generating) simple SPA Applications that already work. Everything is ready, we can go live in a month, as long as the backend team needs to deliver in time. Or even better, let’s just develop directly against the Database. In a variety of user experience discussions, I have learned (sometimes the hard way) that we should not provide pixel-perfect results too early. In first place, it might create false expectations and makes changes to the user journey harder, because wasn’t it already finished? And secondly, we often discuss the wrong things. People are concentrating on colours or animations while the underlying functionality and information architecture also needs to be discussed. While I also don’t agree that server-side prototyping can’t be fast (did you ever build up a nodejs application?), I think that good qualities for prototypes are seldom good qualities for a production delivery.
While I really focus often on the extrinsic arguments for a project, the intrinsic motivation is also definitely important. But we need to be able to prioritise. Try to find your big or long-term goals and ask yourself some questions:
- Is the target something that will be thrown away in three month anyway, or should it be stable without lots of development effort for quite a while?
- Do we need to provide awesome customer-service? If yes, the ability to debug might be a big factor. And with all awesome user monitoring solutions at hand, client-side error debugging can be a nightmare. This can be because of bad stack traces and similar, but also because your browser does not even see the bad behaviour.
- Do we need to integrate to a variety of clients? For instance, do we need to deliver fast deep-links to hybrid mobile applications or IoT Devices? Do we need a small memory footprint for low-profile devices, etc.?
With such a prioritisation at hand, we can make the often implicit decisions more explicit and maybe more fact-based instead of relying on a more emotional view on the different choices.
I also believe that the extrinsic arguments are based on basic business values. The intrinsic arguments might deliver worth, e.g. in terms of cost-reduction or similar, but I think that product decisions should focus a little more on actual end user use cases when we want to choose an SPA framework.
To be honest, my expectation would also be that in an “objective” comparison many of the products we see nowadays are not good candidates for SPA Frameworks. And after honest evaluation, we would choose to develop them in a classical manner. Today’s possibilities for enhancing a server-side application by sprinkling in some simple (and maybe here and there more complex) Web Components into the client are awesome (I personally would do this with custom elements). You can have a rich user experience without moving all business logic and orchestration to the client.
And if the above arguments apply, and you are confident that you can tackle the complexity of an SPA, then in my opinion you have made a good decision!
Wonderful Fox-Fight Photo by cloudvisual.co.uk on Unsplash