Tuesday, 31 May 2016
Recently, I realised that I've been writing single page applications (SPAs) for about seven years. In January 2010, Firefox 3.6 introduced window.onhashchange and I remember eagerly anticipating code without window.location polling. Then, SPAs held a lot of promise: responsive interfaces, a clean separation between data and UI, less code duplication, and faster development times.
Isomorphic frameworks can skip the load time of a hash-bang (or other client-side) URL, and provide a static page to search engines, by emulating their browser APIs on the server. Now a snapshot of your page can be used as a fallback and your SPA can gracefully degrade. Great news!
So, I started asking friends:
Do you still do progressive enhancement? (or at least graceful degradation): if so, what does your JS stack look like today?
Hardly a scientific survey, but the answers on Twitter and offline have been surprisingly consistent: server-side React for graceful degradation, jQuery and possibly shared templates (e.g. Mustache) for progressive enhancement. While the SPA has moved on, progressive enhancement stays steadfastly in 2009. But, in over six years, SPAs still fail to answer the concerns of 2010 effectively. We still re-implement basic browser features, each time in subtly different ways. We still subvert the humble URL. Perhaps that's why many sites still rely on jQuery.
Mustache meets the first requirement. Rendering via a HTML-to-Incremental-DOM compiler could meet the second. To meet all three, perhaps it's time to consider new ideas. I've been trying an approach that I'd like to share.
Below, I've included an experimental Magery template. It looks a lot like Handlebars, but in practice has a few changes.
By incrementally updating the DOM via patch it becomes convenient to rely on a template for all page updates. As both the server and client share the same template, the two sides are easy to align.
In future posts, I plan to explore these features using a progressively enhanced example.
Both are available via package managers: