Hydration

As you may have noticed, I’m a fan of progressive enhancement.

It’s not cool. It’s often at odds with “modern” web development, so I end up looking like an old man yelling at a cloud to get off my lawn. Or something.

At its heart though, progressive enhancement seems fairly uncontroversial and inoffensive to me. It’s an approach. A mindset. Here’s how I describe it in Resilient Web Design:

  1. Identify core functionality.
  2. Make that functionality available using the simplest possible technology.
  3. Enhance!

Progressive enhancement makes use of the principle of least power:

Choose the least powerful language suitable for a given purpose.

That’s step two of the three-step process. But the third step is vital.

I think a lot of the hostility towards progressive enhancement comes from a misunderstanding of that three-step process, perhaps thinking that it stops at step two. I’m sure that some have intrepreted progressive enhancement as preventing developers from using the latest and greatest technology. Nothing could be further from the truth!

Taking a layered approach to building on the web gives you permission to try cutting‐edge JavaScript APIs, regardless of how many or how few browsers currently implement them.

The most common misunderstanding of progressive enhancement is that it’s inherently about JavaScript. That’s not true. You can apply progressive enhancement at every step of front-end development: HTML, CSS, and JavaScript.

But because of JavaScript’s strict error-handling model (at least compared to HTML and CSS), it’s in the JavaScript layer that the lack of a progressive enhancement mindset is most often felt.

That’s why I was saddened by the rise of frameworks and mindsets that assume the availability of JavaScript. Single page apps generally follow this assumption. Everything is delivered via JavaScript: content, markup, styles, and behaviour.

This leads to a terrible situation for performance. The user is left staring at a blank screen, waiting for something—anything!—to appear. Browsers are optimised to stream HTML as soon as they can. Delivering your content via JavaScript rather than HTML means you’re not taking advantage of that optimisation. Your users suffer.

But I was very heartened when I saw the pendulum start to swing back the other way a bit…

Let’s say you’re using a JavaScript framework like React. But the reason you’re using it isn’t because you’re doing anything particularly complex in the browser involving state management. You might be using React because you really like the way it encourages modularity and componentisation.

A few years ago, making a single page app was pretty much the only way you could use React. For you as a developer to experience the benefits of modularity and componentisation, users had to pay the price in the payload (and fragility) of client-side JavaScript.

That’s no longer the case. Now that we can run JavaScript on the server, it’s possible to build in a modular, componentised way and still use progressive enhancement.

When I first heard about Gatsby and Next.js, I thought that was the selling point. Run React on the server; send pre-generated HTML down the wire to the user; then enhance with client-side JavaScript.

But that’s not exactly how it works. The pre-generated HTML isn’t functional. It still needs a bucketload of JavaScript before it can do anything. The actual process is: Run React on the server; send pre-generated HTML down the wire to the user; then send everything again but this time in JavaScript, bundled with the entire React library.

This leads to a situation for users that’s almost worse than before. Instead of staring at a blank screen, now they get HTML lickety-split—excellent! But if they try to interact with what’s on screen, they’ll find that nothing is working yet. Even worse, once the JavaScript is delivered, and is being parsed, they probably can’t even scroll—their device is too busy interpreting all that JavaScript. Your users suffer.

All your content is sent twice. First HTML is sent from the server. These days this is called “server-side rendering”, even though for decades the technical term was “serving a web page” (I’m pretty sure the rendering part happens in a browser). Then a JavaScript library—plus all your bespoke JavaScript—is loaded. Then all your content is loaded again as JSON.

So you’ve got a facade of an interface that you can’t actually interact with until a deluge of JavaScript has been loaded, parsed and executed. The term used for this stage of the process is “hydration”, which makes it sound more like a relaxing treatment from Gwyneth Paltrow than the horrible user experience it is.

The idea is that subsequent navigations—which will happen with Ajax—should be snappy. But the price has already been paid by then. The initial loading experience is jagged and frustrating.

Don’t get me wrong: server-side rendering is great …if what you’re sending from the server is functional. It’s the combination of hollow HTML sent from the server, followed by a huge browser-freezing dump of JavaScript that is an anti-pattern.

This use of server-side rendering followed by hydration feels like progressive enhancement, because it separates out the delivery of markup and scripts. But it’s missing the mindset.

The layered approach of progressive enhancement echoes the separation of concerns in the front-end stack: HTML, CSS, and JavaScript—each layer expressing more power. But while these concepts are related, they’re not interchangable. Separating out the layers of your tech stack isn’t necessarily progressive enhancement. If you have some HTML that relies on JavaScript to be useful, then there’s no benefit in separating that HTML into a separate payload. The HTML that you initially send down the wire needs to be functional (at least at a basic level) before the JavaScript arrives.

I was a little disappointed to see Kyle Simpson—who I admire greatly—conflate separation of concerns with progressive enhancement in his talk from JSCamp 2019:

This content is here. I can see it, and it’s even styled. But I can’t click on the damn button because nothing has loaded in the JavaScript layer yet.

Anybody experienced that where you’ve been on a web page and it’s not really fully functional yet? I can see something but I can’t actually make any usage of it yet.

These are all things that cropped out of our thought process that said: “Let’s build the web in layers. Let’s deliver it progressively in layers. Because that’s morally right. We call this progressive enhancement. And let’s not worry too much about all these potential user experience flaws that may happen.”

That’s a spot-on description of server-side rendering and hydration, but it’s a gross mischaracterisation of progressive enhancement.

That button that requires JavaScript to work? That should’ve been generated with JavaScript. (For example, if you’re building a complex web app, consider sending a read-only view down the wire in HTML—then add any interactive interface elements with JavaScript in the browser.)

If people are equating progressive enhancement with thoughtless server-side rendering and hydration, then I can see why they’d be hostile towards it.

Users would be better served with unprogressive non-enhancement:

You take some structured content, which follows the vertical flow of the document in a way that everyone understands.

Which people traverse easily by either dragging their scroll bar with their mouse, or operating the keyboard using the up and down keys, or using the spacebar.

Or if they’re using a touch device, simply flicking backwards and forwards in that easy way that we’ve all become used to. What you do is you take that, and you fucking well leave it alone.

Alas, that’s not what tools like Gatsby offer. The latest post on their blog is called Why Gatsby is better with JavaScript:

But what about sites or pages where there is no client-side interactivity? Even for those pages, Gatsby offers performance benefits by including JavaScript.

I beg to differ.

(By the way, that same blog post also initially tried to equate the performance hit of client-side JavaScript with the performance hit of images. Andy explains why that’s disingenuous.)

Hope is on the horizon for React in the form of partial hydration. I sincerely hope that it will become the default way of balancing server-side rendering with just-in-time client-side interaction.

The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it (because there’s a cosmetic separation of concerns) but it has none of the user benefits.

Responses

Holger Bartel

The most common misunderstanding of progressive enhancement is that it’s inherently about JavaScript. That’s not true. You can apply progressive enhancement at every step of front-end development: HTML, CSS, and JavaScript. […] Separating out the layers of your tech stack isn’t necessarily progressive enhancement. If you have some HTML that relies on JavaScript to be useful, then there’s no benefit in separating that HTML into a separate payload. The HTML that you initially send down the wire needs to be functional (at least at a basic level) before the JavaScript arrives.

This is a great article on the “approach and mindset” of progressive enhancement. I really like this phrase. After so many years of talking about progressive enhancement, it’s still being widely misunderstood. Also still not cool. While I still think that the PE approach is such a great approach—it doesn’t really matter what and how you’d like to enhance—I’ve always felt there are a few reasons, why it never really caught on, or rather became widely practiced:

  1. It can be a lot of work, if e.g. you want to provide a non-JS solution for everything as a fallback;
  2. A lot of budgets aren’t big enough to cover this amount of work (or PE is not important enough…);
  3. You need to know and understand a lot of web technologies. And if you do, go back to 1.

Matt Derocher

The problem with hydration is that you’re essentially downloading the page twice. You download the HTML first, and then you download the JavaScript bundle with all the rules to re-render that page—not just the parts that will actually change. Via @adactio adactio.com/journal/16404

Daniel Koskinen

From ⁦@adactio⁩: ”The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it […] but it has none of the user benefits.” adactio.com/journal/16404

Michael Scharnagl

The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it (because there’s a cosmetic separation of concerns) but it has none of the user benefits. adactio.com/journal/16404

Adam Silver

Great stuff by Jeremy pointing out the difference between server side rendering+hydration and progressive enhancement. The former has loads of complexity and provides a worse experience (generally speaking). adactio.com/journal/16404

# Posted by Adam Silver on Friday, February 7th, 2020 at 7:08am

Phil Hawksworth

This from @adactio captures my own perspective perfectly. To me, Progressive Enhancement feels as fundamental as spellchecking our content, and I don’t see why we’d discard it. But misunderstandings about what PE means seem to be on the increase. adactio.com/journal/16404

Nick

Good example of folks in the React community making a lot of assumptions and not reaching out to chat with people, Jeremy explains why there’s more to think about: adactio.com/journal/16404

# Posted by Nick on Friday, February 7th, 2020 at 9:24am

Jon Arne S.

Much deserved love to the server-side of the web by @adactio. adactio.com/journal/16404 In light of the deprecation of the User-Agent Chrome is planning I think they are undermining the serving part of the web by motivating for more JS at the rendering end.

# Posted by Jon Arne S. on Friday, February 7th, 2020 at 9:56am

Zeke Farwell

“First HTML is sent from the server. These days this is called server-side rendering, even though for decades the technical term was serving a web page” Thank you, @adactio! I have this exact thought every time I read about server-side rendering. adactio.com/journal/16404

Heydon

“The most common misunderstanding of progressive enhancement is that it’s inherently about JavaScript.” adactio.com/journal/16404

# Posted by Heydon on Saturday, February 8th, 2020 at 12:05pm

Heydon

Among other important insights, @adactio makes the point that “server-side rendering” is a misnomer. The browser renders; the server just makes a string TO render. adactio.com/journal/16404

# Posted by Heydon on Saturday, February 8th, 2020 at 12:09pm

Rasmus Fløe

Woohoo! Finally found something @adactio wrote that I disagree with 😁 “(I’m pretty sure the rendering part happens in a browser)” IMHO server renders HTML - and the browser renders the DOM. I think that is valid 😉 O/w he’s on point - as always: adactio.com/journal/16404

Manuel Matuzović

> Separating out the layers of your tech stack isn’t necessarily progressive enhancement. If you have some HTML that relies on JavaScript to be useful, then there’s no benefit in separating that HTML into a separate payload. - @adactio adactio.com/journal/16404

Daniel Schildt

“Browsers are optimised to stream HTML as soon as they can. Delivering your content via JavaScript rather than HTML means you’re not taking advantage of that optimisation.” adactio.com/journal/16404

Timo

The “server-side rendering” trend is great (aka: serve a web page), but when the goal is progressive enhancement it’s easy to mistake the technicalities for an end result.

Serving HTML and doing something in JS is not “progressive” nor “enhancing” if the HTML is unusable by itself, with visible-yet-nonfunctional UI elements, requiring seconds of interaction-blocking JS execution before it is scrollable and clickable.

Blog post by @adactio

https://adactio.com/journal/16404

Hydration

# Posted by Timo on Sunday, February 9th, 2020 at 7:33pm

Mikkel Rom

This article is a mandatory read if you ask me. @adactio writes about progressive enhancement, server-side rendering, hydration and the misconceptions and pitfalls 👍 All JS-developers should read this ✌️ adactio.com/journal/16404

# Posted by Mikkel Rom on Thursday, February 13th, 2020 at 7:01pm

Peter O'Shaughnessy

Just caught this great post from @adactio last week about server-side rendering and the horrible experience of waiting for ‘hydration’ with a tsunami of JavaScript. Good to know that “hope is on the horizon for React in the form of partial hydration…” adactio.com/journal/16404

Thain

“The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it (because there’s a cosmetic separation of concerns) but it has none of the user benefits” adactio.com/journal/16404

# Posted by Thain on Monday, February 17th, 2020 at 10:25am

Ash Connolly 🚀

Hi Jeremy! 😃 I’ve always wondered what’s the purpose of linking to a page on your site with your tweet reply in it? 🤔

Jeremy Keith

You’ve got the wrong way around. I only post on my site. The tweets (like this one) are copies, syndicated automatically. My website is the canonical source for my notes. The copies have a link back to the source. adactio.com/notes/16447

# Posted by Jeremy Keith on Thursday, February 20th, 2020 at 11:17am

Thomas Allmer

Do we need hydration or progressive enhancement? 🤔 let’s see what @adactio has to say about it: “All your content is sent twice. First HTML is sent from the server. These days this is called “server-side rendering”… 1/x adactio.com/journal/16404

getify

interesting, thanks. missed that blog post.

# Posted by getify on Thursday, April 16th, 2020 at 2:25pm

Scott Jehl

I appreciate the suggestion of exposing more control and options to the user. I had trouble relating to the FOUC problem as an inherent downside of PE, though. We have several options for delivering CSS along w/ HTML to paint early & accurately, & JS can layer gently as well, no?

# Posted by Scott Jehl on Thursday, April 16th, 2020 at 2:34pm

getify

My experience building the web in the trenches from 2005-2012’ish was decidedly pretty ugly in those respects. So I’m pretty battle scarred with those memories. Things are a lot better now, but I don’t think it was that rosy back then.

# Posted by getify on Thursday, April 16th, 2020 at 2:36pm

Scott Jehl

Sure, I can relate to those old challenges (e.g. alistapart.com/article/testdr… ). But even then, we could rely on a stylesheet link to block render until ready, and even inline the CSS to render on arrival. Today, we might server-push CSS w/ HTML. All ways to pair first paint & layout.

# Posted by Scott Jehl on Thursday, April 16th, 2020 at 2:56pm

Ilia Mikhailov

Hydration - a provocative article explaining the current state of the modern JS apps like Gatsby, Nodejs, etc, that no one really talks about. Takeaways: we are building cool modern apps that fetch data twice and are unusable without JS. adactio.com/journal/16404

1 Share

# Shared by Panji Iman Baskoro on Thursday, February 20th, 2020 at 9:00am

11 Likes

# Liked by Chris M. on Thursday, February 6th, 2020 at 10:33am

# Liked by Chris Taylor on Thursday, February 6th, 2020 at 7:21pm

# Liked by Aleksi Peebles on Thursday, February 6th, 2020 at 7:21pm

# Liked by Jake Archibald on Thursday, February 20th, 2020 at 8:16am

# Liked by Ananthakumar on Thursday, February 20th, 2020 at 8:56am

# Liked by Roberto Modica on Thursday, February 20th, 2020 at 8:56am

# Liked by Jaap van Hardeveld on Thursday, February 20th, 2020 at 8:56am

# Liked by Andy Bell on Thursday, February 20th, 2020 at 8:57am

# Liked by Panji Iman Baskoro on Thursday, February 20th, 2020 at 9:38am

# Liked by Keri Hēnare 🏳️‍🌈 on Thursday, February 20th, 2020 at 10:18am

# Liked by Tony Brown ⚛️ ❤️ 💻 👑 on Thursday, February 20th, 2020 at 11:48am

1 Bookmark

# Bookmarked by Webrocker on Saturday, February 8th, 2020 at 10:22am

Related posts

Browser support

Here’s Clearleft’s approach to browser support. You can use it too (it’s CC-licensed).

Applying the four principles of accessibility

Here’s how I interpret the top-level guidance in the Web Content Accessibility Guidelines.

Baseline progressive enhancement

If a browser feature can be used as a progressive enhancement, you don’t have to wait for all browsers to support it.

Hanging punctuation in CSS

A little fix for Safari.

Progressive disclosure with HTML

The `details` element is like the TL;DR of markup.

Related links

Futuristic Progressive Enhancement - Jim Nielsen’s Blog

We’re all tired of: write some code, come back to it in six months, try to make it do more, and find the whole project is broken until you upgrade everything.

Progressive enhancement allows you to do the opposite: write some code, come back to it in six months, and it’s doing more than the day you wrote it!

Tagged with

The web is mostly links and forms | Go Make Things

In the same vein as that last link, Chris says what we’re all thinking:

Most of what we build is links from one page to another, and form submissions that send data from the browser to the server.

Tagged with

12 Modern CSS One-Line Upgrades | Modern CSS Solutions

I love how straightforward these bits of CSS are—time to rip out some of those old complicated hacks and workarounds!

Tagged with

Web developers: remarkably untalented and careless? – Baldur Bjarnason

I’d like to suggest that everybody in web dev point their dysfunctional novelty seeking (of which I suffer as well) in the direction of HTML and CSS. See how much can be done without JavaScript. It’s a lot! Then look at writing more lightweight JavaScript that’s layered on top of the HTML as enhancements. Because it’s an enhancement and not required for functionality, you can cut the line higher and use newer tech without worry.

See how refreshing that feels.

Tagged with

Introducing Enhance Music — Begin Blog

I also think the number of situations in which an SPA architecture can be recommended is dwindling, chiefly due to how good the web platform has become (and how much better it’s getting every day). And because so much of the rest of the ‘struggle stack’ (transpilers, unique dialects, etc.) was built to get around gaps in the web platform that no longer exist, the use cases for these tools is dwindling in tandem.

This is good news: not only can we avoid piling up transient knowledge about a seemingly endless stream of dependencies, we can also eject from the routine stress of those dependencies changing or breaking under our feet and throwing wrenches into our workflows — all while delivering more robust and performant websites to end users.

Tagged with

Previously on this day

10 years ago I wrote Connections: Weak Signals

Popping the Connections cherry in style at 68 Middle Street.

11 years ago I wrote Open device labs

The communal device lab is here for us to use.

17 years ago I wrote Web Directions North, day zero

I’m acclimatising to the time zone.

18 years ago I wrote Buzzword Bingo

I’ve made a game to liven up any buzzword-laden conference.

18 years ago I wrote Everything old is new again

I’ve switch CMSs for this site. It’s still home-rolled.

20 years ago I wrote Apart at last

In this week’s A List Apart: JavaScript Image Gallery by yours truly.

20 years ago I wrote They're my friends

You know how they sometimes do parody ads on South Park or Ren and Stimpy?

21 years ago I wrote Palace Pire

Here are those pictures of the Palace Pier burning taken by Jamie over at Message.

22 years ago I wrote Stormy Weather

There’s been quite a bit of nasty weather here in England lately (nastier than usual, that is).