Progressive enhancement and JavaScript frameworks — a complicated relationship
There’s long been an incompatibility between progressive enhancement (PE) and front-end JavaScript frameworks, making it a real challenge to build modern web applications that satisfy all use cases. However, a step change in front-end technologies means we have more options available. In this article I assess design patterns and use cases whilst considering the business impact so that you can choose the most appropriate course for your project.
What problem does progressive enhancement solve?
A common definition of PE is that it can provide a high level of reliability to users because it ensures the application is usable via HTML alone — other ‘layers’, such as fonts, styles and JavaScript are treated as enhancements. There are notable challenges to that definition but for the purpose of this article that’s the one I’m going with.
To quote Gov.uk, PE attempts to “give all users the greatest chance of success”. Even if the number of visitors whose browser cannot or does not load JavaScript correctly is small, it is not insignificant. Gov.uk conducted a robust test and found that 1.1% of visitors were not getting ‘JavaScript enhancements’. A progressively enhanced website should therefore be usable by close to 100% of users.
What problems do UI frameworks solve?
UI frameworks have solved a multitude of architecture and application design problems. They provide developers with a clear separation of concerns between UI, business logic and data and they handle complex interactions in a scalable way. They allow for component-driven development (CDD), which has transformed how organisations design, develop and manage UI collateral. Templating languages, such as Handlebars, attempted to solve this but they did not offer the power, structure and flexibility that UI frameworks do.
Common architectures
Let’s look at the primary patterns available to us:
SPAs (Single Page Apps)
The UI is presented and managed using client-side scripting (JavaScript) and often a tool like React or Angular.
Why are SPAs so popular:
- A seamless user experience, where only portions of the page update
- The Web UI is highly responsive to user actions
- The UI developer has one unified, modular way to build the GUI
Do they meet progressive enhancement requirements?
The HTML is not rendered on the server and therefore there is no UI for the user to interact with before JavaScript loads, parses and executes. This means they do not meet PE requirements.
PWAs (Progressive Web Apps)
PWAs provide a native app-like experience to users using web technologies. Whilst their name suggests they are built using progressive enhancement, that may not always be the case. However, they employ local caching that treats the network as an enhancement, which gives them the potential to be more progressive than any other form of web app.
Why are PWAs popular?
- Native app-like experience (installable, offline-first, access to hardware features)
- Cross-platform (build once, deploy anywhere)
Do they meet progressive enhancement requirements?
Though PWAs rely on a JavaScript feature called Service Worker, they offer developers multiple caching strategies, so building an HTML-first application that’s installable and works offline is certainly feasible. However, the question of how the HTML is rendered must still be answered. Some PWAs are also SPAs where the content is rendered by JavaScript in which case they would not comply.
JAMStack
Applications built using the JAMStack (JS + API + Markup) approach render pages via the build server and generate the HTML based on changes detected in other software components, such as the CMS, PIM or UI code base.
Why is JAMStack popular?
- Good separation of concerns
- Secure — small attack surface
- Fast because pages are rendered ahead of time
Do they meet progressive enhancement requirements?
JAMStack websites can and do meet PE requirements but, as with MPAs (below), building a rich, dynamic, highly personalised UI may involve employing other patterns which will increase complexity and costs.
Multi-page apps (MPA)
MPAs are the original website pattern where each ‘page’ is loaded from the server when a user navigates to a new document.
Why are MPAs popular?
- Simple to develop and maintain (assuming UI complexity is low)
- Supported by a wide range of experience platforms such as CMS, ecommerce and CRM systems
Do they meet progressive enhancement requirements?
Yes as MPAs rely on pre-rendering either via server-side rendering or static site generation. In both cases each served page presents a UI replete with content and native interactive elements which the user can navigate without JavaScript.
Sub-patterns
It’s worth briefly calling out a couple of sub-patterns that are in use:
- Islands, whereby portions of the page are taken over by client-side scripting
- Streaming, which allows you to incrementally render UI component into the client
In both cases progressive enhancement can be achieved but extra effort will be required to create any fallback content on the server.
Matching architectures to use cases
Laurie Voss, argued that there are two distinct use cases we need to build for: a multipage page app or “site” (static text and images consumed by separate pages e.g. a blog) and a single page web app or “app” (an interactive tool to enable task completion or rich media consumption such as a banking portal). However, there are many web applications that need to cater for a combination of these use cases — as Jeremy Keith says “it’s a spectrum”. This means many large-scale online experiences use a combination of different architecture patterns: server-side rendering (SSR), static site generation (SSG) and client side rendering (CSR). On one recent project I led, the public site was delivered as a static site, so as to meet SEO requirements, and the private members site as a single page app.
Meeting regulatory guidelines
For many organisations PE is a solution design choice, but should you be subject to guidelines like the UK’s CDDO, knowing where to draw the line between providing ‘essential content’ and letting JS take over is difficult.
Gov.uk provide an interesting example of when they make exceptions to the pure PE approach: “Recently we prototyped a web chat system using React. It’s difficult to imagine a base level of web chat that doesn’t require JavaScript, but we will make sure any webchat system we develop has a standard contact form as its barebones”.
Whilst I fully support this approach from an inclusivity perspective, it should be noted that, from a business perspective, this is building two solutions to solve one problem. I would argue that oftentimes the cost is worth the investment as you meet the needs of all of your users. For a busy ecommerce business for example, that investment might pay for itself within a few weeks of release.
If you find yourself in the situation where you need to build a service that is entirely app-like but must support PE, your choices would be:
- Build a native mobile app, which will be exempt from the PE mandate but may inhibit user access due to the distribution limitations of mobile apps (vs web)
- Build a web-based app and an HTML-first alternative, if feasible
- Build a web-based app and provide another acceptable means for users to use the service (such as a call centre)
- Make an exemption case to the governing body based on the complexity of functionality required and associated costs of building two solutions
Can you have your cake and eat it?
With the above in mind, what patterns and tools are emerging that will help us build applications that are both inclusive, engaging and meet the user experience expectations of the masses?
In recent years a new class of frameworks, referred to as rendering or meta-frameworks have emerged. They have been built around the huge UI framework communities and have responded to the need for organisations to build decoupled front-ends that can be rendered in multiple ways whilst still supporting component-driven development.
The most well established meta-frameworks are Next.JS and Gatsby who competed closely for a while. Next.js has emerged as the market leader having won over developers and receiving significant investment from Vercel (formerly Zeit).
Whilst Next.js is relatively mature and certainly popular it has some new challengers, such as Marko, Astro, Fresh, Rocket, and Enhance. Each one offers something slightly different but they are largely focussed on performance and developer experience (DX).
It must be noted that the success of these meta-frameworks is dependent on the success of the underlying UI frameworks they support. Most of them only support one specific tool, as is the case with Next.js (React), Nuxt (Vue) and Sveltekit (Svelte, obvs). A small selection are UI tool agnostic, in particular Astro.
A noteworthy contender that provides a framework for UI development at scale whilst supporting progressive enhancement is Remix. It’s the brainchild of Michael Jackson (not that one) and has a progressive enhancement philosophy that will resonate with many developers. Having recently been bought by Shopify, it’s stands a good chance of being propelled into a market leading position.
Conclusion
In this article we looked at some of the key patterns and tools and considered the use cases and business constraints when building (decoupled) user interfaces for web applications.
This field is going through a major period of growth and change due to the demands being placed on it and it can be difficult to choose the right approach without breaking the bank. Whilst it is great that we have so much choice we still face a deep-seated challenge that has emerged since web 2.0’s inception: Many of us are trying to build native mobile/desktop apps using web technology, which isn’t fit for purpose. Dom’s comment on this blog piece sums it up well:
“We need a common, accepted standard for distributed applications that is not built on HTML, CSS and JS. Everything we have now for HTML has been bolted onto something that was intended for a different use. We need an entire framework for building GUI apps…that is supported by all operating systems and platforms but binary based.”
We do not yet have a single, distributable binary for delivering web UIs yet, but webAssmebly (WASM) has emerged as a potential solution. It could solve the underlying issue, which is that we’re arguably using the wrong technology to build rich web applications. Whilst WebAssembly is gathering momentum and challenging traditional HTML-based applications, it currently has to be loaded via JavaScript and therefore does not meet PE requirements.
In the meantime, we must embrace the options we have and weigh up the cost vs benefit on a case-by-case basis.