React Lazy Hydration
React Lazy Hydration is a library designed to optimize the initial load performance of Server-Rendered React applications by deferring the hydration of components until they are actually needed. This package, currently at version 0.1.0, offers several strategies for lazy hydration, including hydrating only on the server (`ssrOnly`), when a component becomes visible in the viewport (`whenVisible`), when the browser is idle (`whenIdle`), or upon specific user events like clicks or mouse enters (`on` event). It aims to reduce the JavaScript payload executed during initial page load, improving Time To Interactive (TTI). The library is inspired by discussions within the React community regarding selective hydration and similar patterns seen in Vue SSR. Its release cadence is currently irregular as it's in its early development stages. A key differentiator is its flexible approach, allowing developers to choose the most suitable hydration strategy on a per-component basis, rather than a global setting. It depends on React version 16.8.0 or greater for its hooks-based implementation.
Common errors
-
ReferenceError: IntersectionObserver is not defined
cause The browser environment does not natively support `IntersectionObserver`, and no polyfill has been provided.fixAdd a polyfill for IntersectionObserver, such as `import 'intersection-observer';` at the entry point of your application. -
ReferenceError: requestIdleCallback is not defined
cause The browser environment does not natively support `requestIdleCallback`, and no polyfill has been provided.fixAdd a polyfill for requestIdleCallback, such as `import 'requestidlecallback';` at the entry point of your application. -
TypeError: Cannot read properties of undefined (reading 'useState') or similar hooks-related errors
cause `react` is not correctly installed or a compatible version (>=16.8.0) is not available, or multiple instances of React are being loaded.fixEnsure `react` is installed as a peer dependency (`npm install react@^16.8.0` or higher) and check for duplicate React installations using `npm ls react` or `yarn why react`.
Warnings
- gotcha The `whenVisible` strategy relies on `IntersectionObserver`. If targeting environments that do not natively support it (e.g., older browsers), a polyfill must be included manually.
- gotcha The `whenIdle` strategy relies on `requestIdleCallback`. For environments lacking native support (e.g., older browsers), a polyfill is required.
- gotcha As of v0.1.0, an `IntersectionObserver` instance is created per `LazyHydrate` component using the `whenVisible` prop. For applications with a very large number of such components, this might lead to increased resource usage.
Install
-
npm install react-lazy-hydration -
yarn add react-lazy-hydration -
pnpm add react-lazy-hydration
Imports
- LazyHydrate
import { LazyHydrate } from 'react-lazy-hydration';import LazyHydrate from 'react-lazy-hydration';
- LazyHydrateProps
import type { LazyHydrateProps } from 'react-lazy-hydration';
Quickstart
import React from 'react';
import LazyHydrate from 'react-lazy-hydration';
function MyHeader() {
return <h1 className="text-3xl font-bold underline">Hello, Lazy Hydration!</h1>;
}
function MyContent() {
const [count, setCount] = React.useState(0);
return (
<div className="my-4 p-4 border rounded">
<p>This content is hydrated.</p>
<button onClick={() => setCount(c => c + 1)} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Count: {count}
</button>
</div>
);
}
function App() {
return (
<div className="container mx-auto p-4">
{/* This component will only be rendered on the server and never hydrated on the client. */}
<LazyHydrate ssrOnly>
<MyHeader />
</LazyHydrate>
{/* This component will hydrate only when it becomes visible in the viewport. */}
<LazyHydrate whenVisible={{ rootMargin: '200px' }}>
<MyContent />
</LazyHydrate>
{/* This component will hydrate when the browser is idle. */}
<LazyHydrate whenIdle>
<p className="my-2 text-gray-600">This will hydrate during browser idle time.</p>
<button onClick={() => console.log('Idle button clicked')} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
Idle Action
</button>
</LazyHydrate>
{/* This component will hydrate on specific user events (click, mouseenter). */}
<LazyHydrate on={['click', 'mouseenter']}>
<p className="my-2 text-gray-600">Click or hover to hydrate this section.</p>
</LazyHydrate>
</div>
);
}
export default App;