Angular’s Approach to Partial Hydration
Everybody talks about partial hydration and its siblings terms — islands, progressive hydration, donut hydration, selective hydration — but what does it mean? And do frameworks actually support partial hydration?
Google Senior Software Engineer Jessica Janiuk, who works on the Angular framework team, spent six to eight months researching partial hydration. What she found is confusion and disagreement over the terminology, a lot of lip service, and yet not too many frameworks that actually support forms of partial hydration, she said during a webcast of the Oct. 10-11 Web Unleashed conference.
What Is Hydration, Anyway?
Janiuk noted there was a lot of confusion about what hydration actually means, so she began by defining it.
“It is a server-side rendering initial load optimization for web apps,” she told the audience. She then walked through what actually happens during hydration.
“We’ve got a little happy web server here, and that web server has your application on it,” she said. “That web server is like, ‘Great, I’m going to render that out,’ but what it actually just does is it generates some DOM nodes.”
The DOM nodes end up being just a string that is passed off to the client browser, which render the HTML, she continued.
“It’s going to look like your application because it has the style sheets and everything that’s part of what the server rendered for you,” she said. “But it doesn’t know anything about the JavaScript yet, so it’s like, really confused — there’s supposed to be an application here.”
The hydration process is essentially causing the browser to load the application.
So it will fetch the application’s JavaScript, which then gets bootstrapped, she said.
“This is part of every web framework or every application, [it] has to run a function that wakes up the application and bootstraps all of your dependencies and components and anything that you’re using,” she explained. “It’s not just web frameworks that do this. Pretty much every piece of code out there has to bootstrap somehow.”
The hydration process is essentially causing the browser to load the application.
“It’s the meshing together of the DOM that was rendered by your web server and the application waking up and identifying what that DOM is — that’s the process of hydration, remeshing together your application code with the DOM,” she said.
Rather than fully hydrate the application immediately, partial hydration allows developers to identify portions of their application — maybe a footer or something that a user will not immediately need to see — and rather than ship all of the JavaScript in the app, it “hydrates” only the parts that are needed immediately.
“Partial hydration [is] the concept that you don’t have to do the whole thing,” she said. “The existing terminology in this space — and this was part of the research process that I underwent to understand the space — if you google partial hydration, you’ll see a lot of hits. But what we learned is that no one agrees on what that means, and there’s a bunch of them.”
Partial Hydration’s Not-So-Great Alternative
The alternative, Janiuk said, is to do what Angular did a few versions back. They called it destructive hydration.
“Which was really just a code word for we don’t hydrate — we just destroy what’s there and repaint it,” she said. “It’s just not optimal. In that situation, the application goes, ‘I don’t care what’s there before, I’m just going to wipe it all and I’m going to re-bootstrap and repaint everything on the client side.’ But there’s some big downsides to that, because hydration is better. If you do that destruction, it’s going to have a pretty negative impact on your core web vitals.”
Core web vitals are the metrics that are used to measure the performance of your application or webpages, she added.
“You’re going to see if you do that destructive version, like your CLS (Cumulative Layout Shift), your layout shift, it’s going to be seen as a whole application layout shift, and there’s a flicker, and […] the duration that it takes before [the] shift is done will be much later. Same with your LCP (Largest Contentful Paint) and your FID (First Input Delay), it’s going to delay everything so you have a longer period of time. That’s why hydration is important.”
Editor’s Note: Google replaced FID with Interaction to Next Paint (INP) in March 2024, however INP looks at the latency of all user interactions, not just the first one.
Understanding the Types of Hydration
There’s a lot of talk about partial hydration but the reality is there’s not a lot of actual partial hydration happening, Janiuk said.
“Partial hydration has become kind of like a trendy topic amongst framework authors and some folks in the industry,” she said. “What we learned is that no one agrees on what that means.”
That’s not all she learned from her research.
“We actually were quite surprised because with all the talk that we’ve heard about partial hydration, it doesn’t really exist much,” she added.
Variations on Partial Hydration
Even though it’s not as widely supported, there are a ton of terms to describe partial hydration, all with a slight variation on the theme, she learned.

Google Senior Software Engineer Jessica Janiuk explains Islands, a partial hydration approach. Screenshot via Web Unleashed.
Islands: This refers to an approach that enables “islands” hydration on a web application. The JavaScript framework Astro uses this approach.
“If you imagine a little oasis in the middle of a desert, the desert is dehydrated. The island in the middle is hydrated. You’ve got an island of interactivity; it’s all surrounded by dehydrated content,” she said. “It may not be detached. It depends on the implementation. It could be an isolated application. For example, if you use Astro, you can create individual little light islands with Astro, and those are independent of each other. It may share data. It may share dependencies.”

Janiuk explains Donut hydration, which is a form of partial hydration. Screenshot via Web Unleashed.
Donut Hydration: The term isn’t used a ton, she said, but the Angular team uses it because it “accurately describes the concept of the donut being what’s hydrated and the donut hole part of it being what is not hydrated, she explained. It’s very similar to what Angular ended up implementing, she added.
Donut Hole hydration: The hole is hydrated, but the surrounding “donut” is not.” “This is essentially the equivalent of islands,” Janiuk said. “It’s the inverse of donut hydration.”
Selective Hydration: This is a type of partial hydration that requires streaming. “As your components are streaming in, they remain dehydrated up until that streaming has finished for that component, and then it actually hydrates that component,” Janiuk said. “So it’s not really like a lot of the other types of hydration we talked about because it’s solely reliant on streaming.

Janiuk explains Selective Hydration. Screenshot via Web Unleashed.
Progressive Hydration: Selective hydration is one aspect of progressive hydration and is used in React’s concurrent mode, she said. It’s similar to what the Angular framework will be doing, she added. It’s designed to generate smaller chunks for the components the developer chooses. Developers can specify the sequence in which chunks will be loaded and hydrated. Technically, this is available in Angular, but it relies on an experimental API and requires Angular V18 or later. She wasn’t sure how frequently it was being used, however, and noted that it’s possible Next.js may use this approach, but she wasn’t sure.

Janiuk explains progressive hydration, which is available in React. Screenshot via Web Unleashed.
What the Frameworks Offer
Vue: “What we found is that there is just no native support for it [partial hydration]. It’s been talked about. We found a community library that some people are probably using, I don’t remember which version it supports for Vue, but there was essentially a proposal that was written up within the Vue repo to add core support for it, but it hadn’t really gone anywhere,” as of her research a few months ago, Janiuk said.
Svelte: “Svelte, similarly, has no native support in SvelteKit,” she said.
Solid: No native support yet. Although Ryan Carniato, creator of Solid, has talked about it with the Angular team, he said there are no plans to implement partial hydration in the short term because the team is focused on SolidStart right now. “Maybe after we launch ours, he’ll, he’ll consider it,” she said.
Astro: Astro does implement partial hydration as islands. It allows you to share data across the islands, Janiuk said.
“What we found is that data has no impact on whether you want to wake up on an island,” she said. “If the data changes between them, you still have to use a different trigger to walk them up. They are essentially isolated from each other, other than being able to share that data.”
Wiz and Qwik. Wiz is an internal Google framework and inspired Qwik because “it is the original resumable framework,” she said. Google is trying to find primitives and “synergies” between Angular and Wiz now.
“These are frameworks that are essentially designed around that initial load optimization,” she said. “They essentially reduce the amount of JavaScript that they ship to almost nothing. There’s a little bit that’s shipped right away, and then they’ll defer load as much as they possibly can.” People will talk about Qwik shipping no JavaScript, and that may be true for the first load, Janiuk said, but as developers use components, they start to wake up, and it does actually have to fetch them at that point.
“Partial hydration is really just a byproduct of these,” she said of the frameworks. “It’s built-in because if you’re not loading any JavaScript to load your page, and you’re only loading it when it’s needed, [so] it’s naturally only going to have little spots on the page that are interactive.”
Angular’s Incremental Hydration Approach
Angular has decided to call its approach to partial hydration “incremental hydration” because they felt the terminology was “all over the place,” she said. Introducing this to Angular has been a “huge, multi-year effort” that required building on top of and enhancing new features over several versions. For instance, it shipped deferrable view in version 15.
“Deferrable views are our native lazy loading built-in framework primitive for being able to defer load chunks and specify when those load,” she said. Deferrable views allow components to delay rendering their content until they become visible in the viewport, thus improving perceived performance and reducing initial load times.
Then, in version 18, they shipped event replay.
“Essentially, the idea behind that is when you do full app hydration, there’s a period of time before hydration has occurred that your site is there, but it’s not really interactive. People can click on things and it doesn’t do anything, and those clicks are lost, typically,” she said. “We worked with the Wiz team and used a library that they created called JsAction, which is this tiny little library that allows those events to be captured and queued up, and then once your app bootstraps, it replays all of them in the same sequence that they were clicked in, so none of that interactivity is lost.”
It’s an open source library that was a native part of Wiz, she added, and it’s now in the Angular framework. The library is specifically designed around events that the browser supports, so anything that’s native — clicks or hovers, for instance — but not something like an intersection observer, because that’s a separate class to implement, she said.
“This is how we’ve enabled partial hydration: essentially, you create your defer block. You’ve got one trigger, and then you can specify, hey, but I wanted to hydrate on this separate trigger.”
— Jessica Janiuk, Google Senior Software Engineer
Defer block also plays a role. Defer blocks in Angular are used to delay the execution of certain parts of a component’s template until they are needed. Developers can specify what will trigger the interaction — for instance, could be a click, a direct interaction, a callback.
“This is how we’ve enabled partial hydration,” she explained. “Essentially, you create your defer block. You’ve got one trigger, and then you can specify, hey, but I wanted to hydrate on this separate trigger.”
“We think this is pretty, pretty awesome way to specify because it’s not too much code, and you kind of just get it out of the box,” Janiuk continued. “What’s cool is that those triggers essentially tell your server that, rather than rendering a placeholder just on the server, ignore that this was supposed to be deferred, fetch all those dependencies, render it through on the server, and then when you get to the client, that content is still deferred, so you actually get your real template code as your placeholder in that case, which is exactly what you want.”
And it does so without a layout shift, she added.
Angular has separate code that handles anything that’s not a native browser event, it has additional instructions, and it requires developers to perform “annotation” as well.
“Annotation is a big part of hydration because in order to know what’s there, we have to serialize all this information about the DOM so that when the application bootstraps, it can look at that and be like, so how many root nodes are here? There are five, okay. And then do we need to know about any content projection? What about a control flow? What if there’s an if?” she said. “So we have to have all of this information as it’s serialized into the footer; we read that during the hydration process.”
Janiuk said the new features will likely be available in version 19, which is coming in November, so developers should be able to play with it in the upcoming release candidates.