Partial Hydration enables you to selectively add interactivity to your otherwise completely static app. This results in improved frontend performance while keeping the benefits of client-side apps. Gatsby uses React server components to achieve this.
In recent years the idea of “island architecture” (e.g. post by Jason Miller) was created and heavily pushed forward by Astro. The simple idea is to create islands of interactivity that can be hydrated independently, leaving out the rest of the page as it can stay purely static HTML. So is Partial Hydration an implementation of the “island architecture” then? Not really. As Ryan Carniato points out the end result (islands of interactivity) is the same, but how you get there is different between e.g. Astro’s Islands and Gatsby’s Partial Hydration. You can read more about this in the Why React Server Components? section.
You could see this as a super-powered way of doing code-splitting on your components. You’re using a heavy library that is only used during the SSR phase? Then you don’t need to ship it to the client!
By using Partial Hydration you can shorten that time or completely remove the uncanny valley.
How Partial Hydration works in Gatsby
As mentioned, Gatsby’s Partial hydration feature is built upon React server components so the detailed design can be read in the server components RFC.
By default, Gatsby marks all components as server components starting from the top level pages (e.g.
page-data-rsc.json files are requested. The JSON file is a description of the UI and client components are included as a bundle reference (to get the actual code of the component). This is also why props you pass around need to be serializable, as they are written into a JSON file.
You can use server components and client components throughout your app together. React will behind the scenes merge them together.
During Gatsby’s build process all components are looked at and a manifest is created that maps all client components and their individual chunks. With the help of that manifest the RSC output can then be generated.
Why React Server Components?
If you don’t know what React server components are or need a refresher, we recommend watching the talk introducing Server Components or reading the Server Components RFC.
So why is Gatsby using React server components to achieve Partial Hydration and didn’t shift to the island architecture? In a nutshell: To allow you to (mostly) keep writing your apps as you’re used to.
In island architecture world you’re authoring individual island layers that each have their own context and React tree. This means that you can’t just share context or bubble up/down of React events, you have to implement custom logic to connect those islands. You need to think differently when creating your app. Islands also don’t work for SPAs as they can’t render the complete page, leading to more sluggish navigation between pages. With React server components you can keep writing your app like you’re used to, for the most part. There are of course constraints you have to follow with them but it’s not a complete paradigm shift.
Some of the benefits of React server components are:
- Zero impact on bundle-size
- Server components integrate seamlessly with client components
- Subtree and component-level updates that preserve client state