Google’s AMP is an attempt to improve the performance of articles on the web.
SSR and Isomorphic JS
Server-side rendering seems to be incredibly popular at the moment. The idea is to use React (or equivalent) on the client-side but with a faster first paint (and FMP) than would otherwise be possible. The way this works is that initial markup is produced on the server, using Node/Express.js for example, and then the client-side framework binds or ‘hydrates’ this on the client to introduce any dynamic behaviour.
SSR is both an architecture and a technology choice and there are significant pros and cons associated with it.
AMP is explicitly designed for publishers and article/blog-style content and it does seem well-suited to that space.
But we also see notable publishers choosing the SSR/React-all-in model. For example, the NYT site is entirely React-driven in this way.
The two approaches are entirely, completely, at odds it seems, but appear to be operating in the same space!
Lessons from AMP
As a self-professed full-stack* developer and, at the time of writing, tech-lead for www.theguardian.com, I’ve been thinking about which approach is best for my beloved Grauniad. And I’ve come to the conclusion that the AMP approach is ultimately the better way for us.
By ‘AMP approach’ I mean loosely: a server-side that produces markup, and dynamic behaviour introduced by markup-driven web-components on the client-side. I do not mean the exact AMP libraries and that specific implementation. If you are not familiar with how AMP works, it is probably worth taking a brief look at some of their examples at this point before reading on.
This conclusion is of course specific to our context:
- we are a publisher of mostly text-content
- we have a very large audience, the majority of whom are not signed-in/regulars
- we want our journalism to reach as many people as possible, whatever their device or connection speeds
- we have a relatively complex site - plenty of layout types, and other subtle differences and combinations of visual design
- our site and content is completely free but we offer premium experiences (mobile native apps, and an editions product)
- we have lots (say 50) developers of a wide-range of skills and backgrounds writing both server and client-side code on the site
So why do I like the AMP approach and what are my concerns with the SSR/hydrate alternative?
Architectural decoupling is the most important thing when it comes to agility over the medium-long term for larger software services.
- it tightly couples server-side templating with client-side interaction
- it couples different page components together into a single library and runtime
If you are producing a SPA or highly-interactive website, then the isormorphic approach may justify itself, but a publishing site is not such a great fit. The short-term benefits of the isomorphic approach are likely to be dominated in the medium-long term by the coupling constraints and eventual forced re-write down the line.
In contrast, AMP is relatively decoupled:
- you can use any server-side approach, it just has to return HTML
- it uses web-components under the hood
Web components are a web standard and can be (re-)written in any combination of client-side technologies.
The great thing here is that you can mix and match technologies across the entire stack. Want to try out using Python to generate markup for one section of the site or page type? Easy! As long as the relevant markup is the same, the client-side behaviour will stay the same. Want to experiment with using a new library to build some of the web-components? Again, it’s easy to do this alongside your existing technology choices.
We should be very cautious about foregoing these important forms of decoupling in our architectural choices.
An important caveat is that AMP is not fully decoupled; a core runtime is still required to manage performance-critical operations - network requests and DOM operations.
Russell Cox, of Go(lang) fame, has defined software engineering as
what happens to programming when you add time and other programmers
It is a human problem, but nonetheless critical, to ensure good performance of the site as new features are added over time. Experience has taught me that convention is an ineffective solution to this problem.
The key assumption of the AMP-approach here is that, for a publishing site, the vast majority of client-side behaviour can be encapsulated in a small set of client-side components.
Provided these components are well-written and performance tested, developers can add client-side behaviour without the risk of damaging client-side performance.
A core web team can steward these components without having to review every PR (which is in any case unrealistic).
Now, of course it is possible to introduce linting, or other tooling approaches with SSR to achieve something similar. But I much prefer the significant layer of friction the AMP approach introduces here to adding new client-side behaviours.
Before you write me off as some kind of control freak, it’s worth remembering that performance is absolutely crucial to our core mission so it is worth being radical to help achieve it. Fast performance is hugely associated with improved engagement, it ensures people with poor connections (more likely in poorer countries) can still access our content without it costing a fortune and/or taking forever to load, and it significantly impacts our SEO performance too.
One motivation for Isormorphic JS, and something the NYT cite in their blog posts, is the desire to use a single codebase across multiple-platforms. React Native is increasingly powerful and offers the promise of one codebase but with native behaviour on web and app (and potentially other platforms too).
I’m not familiar enough with React Native to comment on this in detail, although the scope of this kind of solution seems ambitious; it seems likely that any abstraction across platforms will be quite leaky.
But I’m not aiming to criticise the NYT here! Our product offerings are quite different. The NYT site is a premium experience - they have a (partial) paywall - so it may well make sense to aim for a similar app and website experience. In contrast, the Guardian website and apps are very different. Our website is entirely free, whereas the apps are designed to be a premium experience. The audiences are very different; one is largely unknown and irregular, and the other is known and loyal. It is difficult to see this product strategy changing in the near to medium term so standardising on a single technology for the two doesn’t make sense in our case.
Can I still use Node?
Some of you are reading this and thinking: this is all really obvious! Isomorphiic JS is meant for highly-interactive sites (‘apps’) but not for news sites!
And basically, I think this is right, albeit the arguments are subtler and the tradeoffs larger than people sometimes realise.
- JS is likely much more accessible to client-side developers and designers than some other server-side languages (we use Scala at the Guardian which is definitely not accessible to this audience)
- JSX is a sensible approach to generating HTML
- CSS-in-JS is a great way to encapsulate styling; the approach is language-agnostic but the most popular and mature implementations seem to be in JS-land (we use Emotion for example)
What’s more, if you stick to non-isomorphic JS, the usual JS tooling nightmare (webpack, babel setup to do hot-reloading and all the *-ifications) simplifies dramatically.
* I use this term loosely. My background is as a server-side developer, but for the last couple of years I’ve been working on both client-side and server-side concerns and so now have delusions of client-side mastery.