DEV Community

Tirth Bodawala
Tirth Bodawala

Posted on

When to use hydrateRoot for best UX and Core-Web-Vitals?

Hi Everyone,
I have a question regarding server-side rendering in React using the renderToPipeableStream method from react-dom/server. I am unsure about the best practice for hydrating the application on the client side to achieve optimal Core Web Vitals scores and user experience.

Here are some points to consider:

  • Our app uses Suspended components with React.Suspense and React.lazy, and we also use React for loading data in suspended mode.
  • We use a bundler like webpack/esbuild to generate the output files server.ts and /js/client.mjs. The paths in the example below are for explanation purposes only and may not be accurate.

Question:

My specific question is: should we hydrate the application only after the page fully rendered with all suspended components rendered, or should we hydrate it as soon as the client script file is loaded?

Here's a sample of our server.ts code:

import App from './app';
import { renderToPipeableStream } from 'react-dom/server';

// ... 

renderToPiepableStream(<App />, {
  bootstrapModules: ['/js/client.mjs']
  // ... other code
  // onShellReady() {
  //  response.setHeader('content-type', 'text/html');
  //  pipe(response);
  // }
});

Enter fullscreen mode Exit fullscreen mode

And here's a sample of our /js/client.mjs code:



const render = async () => {
  // Code splitting for react-dom/client
  const { hydrateRoot } = (() => import('./react-dom-client-xsd21.mjs'))();
  // Code splitting for ./app
  const { App } = (() => import('./app-hash2121.mjs'))();
  hydrateRoot(
    document.getElementById('root'),
    <App />
  );
};

if (document.readyState === 'complete') {
  render();
} else {
  addEventListener("readystatechange", (event) => {
     if (document.readyState === 'complete') {
       render();
     }
  }, { passive: true });
}

Enter fullscreen mode Exit fullscreen mode

Some additional questions I have include:

  • Should I lazy load React and react-dom/client?
  • Should I lazy load the App component?
  • Should I wait for the page to fully load before hydrating, or can I start hydrating when the document.readyState is interactive?

I appreciate any assistance, and apologize in advance for any code typos or poor implementation examples.

EDITED:
Follow-up question:

Does partial hydration help with improvements in core-web-vitals?

I was going through the blog and saw the concept of Partial Hydration, Which Gatsby also utilizes and I think might be the base for Server Components as well.
Please correct me if I am wrong.

Top comments (0)