Heyjiawei Blog

How can partial hydration, progressive hydration be accomplished in React Part 1

May 14, 2021

What is hydration in web application

To explain hydration we first need some background on how web applications can be created. There are different ways to server HTML to the users browser and these days, developers use front end frameworks like React and Vue to build web user applications.

Server side rendering and static rendering can both have their content generated before reaching the user’s browser. Upon reaching the user’s browser, these frameworks will kick start the process of “hydration” which then adds interactivity back into the HTML document. You can think of it as attaching event listeners to the HTML content when the content reaches the browser.

What is partial hydration

I understand partial hydration of a web as hydrating only certain parts of the web application. An example of this would be choosing to hydrate one or a few components only within a page. On the code level, the server and client (the user’s browser) may run different code like so:

// Page.js runs on both server and client
function Page() {
  return (
    <Text />
    <Ads />
  );
}

// Ads.js runs on both server and client
function Ads() {
  return <div>Here are some ads</ div>
}

// Text.server.js
function Text() {
  return (
    <div>Click here
      <button onclick={window.alert('NOPE')}>BUTTON</ button>
    </div>
  );
}

// On client side, Text component runs as follows.
// This component's hydration is skipped.
// Text.csr.js
function Text() {
  return <div dangerouslySetInnerHTML={''} suppressHydrationWarning />;
}

In this example, we see that <Ads /> component is hydrated whereas <Text /> component hydration ends at it’s root <div>. This will cause <Text /> component to not get hydrated and thus, no interactivity will be attached to them. This means they will not re-render when new props are passed into them. They will not be interactive so if you clicked the button rendered within within Text component, nothing would happen.

What is progressive hydration

When the page reaches the user’s browser, the hydration phase kicks in. During this hydration phase, all components that require interactivity are all hydrated during this phase. Just imagine 100 components being hydrated all at once, on page load. The idea of Progressive hydration suggest spreading out this huge hydration task so as to reduce the huge initial CPU activity when the page loads.

Flatten the curve. Does it sound familiar?
Flatten the curve. Does it sound familiar?

Here’s the talk about it in Google IO 2019:

Conceptually, here’s what will happen:

  1. The Server renders HTML string (Rendered UI) and adds it into HTML
  2. The Server serializes data for UI and adds it into HTML <script> tag
  3. Only after bundle.js finished loading and executing then UI will be interactive

So how do you skip React hydration?

When you use dangerouslySetHTML as an empty string in a <div> (or dom element), it stops react from walking down the tree. So on server side, if we return the rendered DOM components. We can use dangerouslySetHTML to signal to react to stop hydrating this subtree.

Here is a code example of how we can skip the initial hydration:

public/index.html mimics the server rendered HTML. On client side, we need to ensure that the DOM structure matches. In this instance, App returns a <div>, so Counter have to match up with rendered DOM structure within <div>.

Do note that when you set a component to skip rehydration, all its children will follow and skip hydration too.

// On server side
function Container({ children }) {
  return <div>{children}</div>
}

function Page() {
  return (
    <Container>
      <Text />
      <Text />
      <Text />
    </Container>
  )
}

// On Client side, you will not be able to reach Text.
// Passing in children will not cause this component to re-render
function Container({ children }) {
  return (
    <div suppressHydrationWarning dangerouslySetInnerHTML={{ __html: "" }}>
      {children}
    </div>
  )
}

In the next blog post, I will show some experiments and strategies of progressive hydration.