Feature Request: Hook or API to detect successful completion of initial hydration
Which @angular/* package(s) are relevant/related to the feature request?
platform-server
Description
We've run into issues with hydration from time to time when a new feature would break hydration but we wouldn't notice for a while.
Currently, we manually check for hydration success by watching for the angular hydrated n components message in the console, which is not ideal for automation or robust testing.
To avoid this, we want to add an additional e2e test to our codebase, that checks whether initial hydration was successful or not.
But there seems to be no straightforward way in Angular to programmatically detect when the initial hydration process has completed and the application has become fully stable for the first time.
Proposed solution
Introduce a hook, event, or public api that allows developers to detect when the initial hydration process has completed and the application is stable for the first time. This could be a lifecycle event or a promise that resolves when the initial hydration is done. We don't care about deferred hydration components.
Basically the same as the angular hydrated n components message but as api.
Alternatives considered
We're thinking of using isStable for the time being to detect when the app first becomes stable, but because the application has become stable doesn't necessarily mean that hydration was successful. There can be other issues stopping hydration from working properly, like html mismatch etc.
There's actually already an API for this. You can rely on the AfterNextRender hook. This was developed intentionally to run after hydration finishes and is safe to use for this purpose.
Wouldn't this hook also be run if hydration fails and the component fully recreated? Our goal is to figure out whether hydration was successful or not. From what I understand, the AfterNextRender hook only tells us that the component has been rendered and is now fully functional.
If you're looking for a component level hook, that's a different story and wouldn't really work. Hydration is a process that may leave some dehydrated content behind on purpose for a number of reasons. It also doesn't run on a per component basis. Hydration is happening on the entire page and then cleans up the remaining dehydrated code at the end of that process. So you wouldn't be able to hook into it like that. This is why afterRender is appropriate, because that is an application level hook, and not a component level hook.
I think we're talking about different things. I've renamed the issue to hopefully be a bit clearer on our intent.
Yes, AfterNextRender will run after hydration, but it will also trigger if components have been recreated instead of hydrated.
There is no way to detect if there were any issues during hydration or whether the application ever became stable.
To illustrate the case I've created a minimal reproduction here: https://stackblitz.com/~/github.com/MarcoGlauser/hydration-issues?file=src/app/hydrated-component/hydrated-component.component.ts
The setTimeout() will cause hydration issues and should be caught by our test suite, since the application can't hydrate within 10 seconds.
If you look at the console output, after 11 seconds you'll see the following:
afterNextRender hook called
Angular is running in development mode.
NG0506: Angular hydration expected the ApplicationRef.isStable() to emit `true`, but it didn't happen within 10000ms. Angular hydration logic depends on the application becoming stable as a signal to complete hydration process. Find more at https://angular.dev/errors/NG0506
hydration delayed by 11 seconds
Angular hydrated 2 component(s) and 5 node(s), 0 component(s) were skipped. 0 defer block(s) were configured to use incremental hydration. Learn more at https://angular.dev/guide/hydration.
AfterNextRender was triggered at the very beginning, before hydration could be run, since the application wasn't stable yet. So it doesn't provide us with any information whether the initial hydration was successful or not.
So what we're looking for is a hook for when this message gets logged:
Angular hydrated 2 component(s) and 5 node(s), 0 component(s) were skipped. 0 defer block(s) were configured to use incremental hydration. Learn more at https://angular.dev/guide/hydration.
That way we can add a test to hopefully make sure that hydration actually ran without issues within 10 seconds or less.
We can't test against the console output, since it's only logged by dev builds. But we're testing our production bundle with e2e tests.
Created a PR https://github.com/angular/angular/pull/63833 to get the discussion going.