DEV Community

Discussion on: Why Efficient Hydration in JavaScript Frameworks is so Challenging

Collapse
 
redbar0n profile image
Magne • Edited

@ryansolid Here’s a crazy idea:

Progressive Eager Hydration - with JavaScript streaming and execution by way of HTML streaming.

The goal is to make partial pages interactive asap, so the user can interact above-the-fold immediately (while the rest of the page is also made interactive asap, without the disadvantage of laziness: surprise stall on user interaction).

Could JavaScript be streamed in, in parallel with the HTML, and then progressively but eagerly hydrated (top down) incrementally, as the HTML is streaming in?

I imagine rendering would could go in progressive lock-step (after the HTML and JS streams in parallel): render some HTML -> hydrate corresponding JS component -> render some more HTML -> hydrate corresponding JS component -> … etc.

The framework would need to inject intermittent script tags in the HTML, in a very finely grained manner. Since heavy operations inside a component would block the rendering. Devs would also immediately get aware of slowdowns and optimise above-the-fold components. All so that the JS can be executed during streaming before the entire page is loaded:

Run JS before all HTML has loaded

Maybe this would be more line with the original vision of the web (before we collectively decided to put all JS inside a single script tag at the bottom of the HTML).

Collapse
 
redbar0n profile image
Magne • Edited

FFR, adding a small code example with preview of the basis of this idea. When loading this HTML, the JS executes synchronously in between the rendering of each section of HTML:

<!DOCTYPE HTML>
<html>

<body>

  <p>Before the script...</p>

  <script>
    alert( 'Hello, world!' );
  </script>

  <p>...After the 1st script tag.</p>

  <script>
    alert( 'Hello, again!' );
  </script>

  <p>...After the 2nd script tag.</p>

  <script>
    alert( 'Hello, once more!' );
  </script>

  <p>...After the 3rd script tag.</p>

</body>

</html>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ryansolid profile image
Ryan Carniato

This is how Marko works with in order streaming. In a sense it is how Solid and React's out of order streaming works. Not necessarily splitting it above the fold, but rather based on async data. Now making it work above the fold isn't that far from how things like Astro work with intersection obvserver. I think eager generally is good if it isn't blocking. React has termed "Selective Hydration" as this approach.

All that being said Resumability may be just better than all of this because then the code never needs to run. I think the conversation with Qwik gets too often pulled into the lazy loading story. That isn't the important part for a lot of things. Hard to do less work than eliminating Hydration.

Collapse
 
redbar0n profile image
Magne • Edited

hey @adrienpoly @marcoroth this approach could maybe be used with StimulusJS to make the page interactive faster, while the HTML and JS are being streamed in. You could have Rails interleave Stimulus controllers in JS script tags in the HTML immediately after the HTML tags with the corresponding data-controller attribute (you could even mark the script tag async, to progressively load it from the server and it will «hydrate» and make the HTML interactive asap). So the user doesn’t have to wait until all the JS is downloaded to start interacting (above the fold, for instance). Not sure if this is what Rails with Stimulus already does though…

Collapse
 
redbar0n profile image
Magne

Maybe you could even offload Hydration to a separate thread (web worker) that runs in parallel with the HTML being streamed in.

github.com/BuilderIO/partytown

An initial script tag at the top of the page could set the JS framework off on a separate worker thread, and the framework would need to take in (or listen to) the HTML/DOM as it becomes available, and then hydrate it incrementally. Not sure how wise it is to rely on support for web workers, though.

Collapse
 
ryansolid profile image
Ryan Carniato

Maybe.. but I think we can just do better doing less work still. Party town is cool because what it does is super low priority, no one is waiting on it. But using a worker like this much slower for working with the DOM. Solutions are getting too fancy with deferring when we should just be focusing on doing less work. Resumable Hydration is great, Partial is great at mitigating it. Progressive has its usage but is very overrated.