Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fiber] Highlight hydration and offscreen render phases #31752

Merged
merged 1 commit into from
Dec 14, 2024

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Dec 13, 2024

This highlights the render phase as the tertiary color (green) when we're render a hydration lane or offscreen lane.

I call the "Render" phase "Hydrated" instead in this case. For the offscreen case we don't currently have a differentiation between hydrated or activity. I just called that "Prepared". Even for the hydration case where there's no discovered client rendered boundaries it's more like it's preparing for an interaction rather than blocking one. Where as for the other lanes the hydration might block something.

Screenshot 2024-12-12 at 11 23 14 PM

In a follow up I'd like to color the components in the Components tree green if they were hydrated but not the ones that was actually client rendered e.g. due to a mismatch or forced client rendering so you can tell the difference. Unfortunately, the current signals we have for this get reset earlier in the commit phase than when we log these.

Another thing is that a failed hydration should probably be colored red even though it ends up committing successfully. I.e. a recoverable error.

@sebmarkbage sebmarkbage requested a review from acdlite December 13, 2024 04:28
Copy link

vercel bot commented Dec 13, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 13, 2024 4:30am

@react-sizebot
Copy link

Comparing: d5e8f79...1cdf20f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 510.72 kB 510.72 kB = 91.37 kB 91.37 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 515.63 kB 515.63 kB = 92.07 kB 92.07 kB
facebook-www/ReactDOM-prod.classic.js = 595.55 kB 595.55 kB = 105.06 kB 105.06 kB
facebook-www/ReactDOM-prod.modern.js = 585.82 kB 585.82 kB = 103.49 kB 103.49 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 2c6122b

Copy link
Member

@rickhanlonii rickhanlonii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sick, i like green and eventually red as signals and the naming.

Taking a mental note that when we ship this we'll want to have DevTools docs with the names of these things documented so people understand the concepts

sebmarkbage added a commit that referenced this pull request Dec 14, 2024
Related to #31752.

When hydrating, we have two different ways of handling a Suspense
boundary that the server has already given up on and decided to client
render. If we have already hydrated the parent and then later this
happens, then we'll use the retry lane like any ping. If we discover
that it was already in client-render mode when we discover the Suspense
boundary for the first time, then schedule a default lane to let us
first finish the current render and then upgrade the priority to sync to
try to client render this boundary as soon as possible since we're
holding back content.

We used to use the `DefaultHydrationLane` for this but this is not
really a Hydration. It's actually a client render. If we get any other
updates flowing in from above at the same time we might as well do them
in the same pass instead of two passes. So this should be considered
more like any update.

This also means that visually the client render pass now gets painted as
a render instead of a hydration.

This show the flow of a shell being hydrated at the default priority,
then a Suspense boundary being discovered and hydrated at Idle and then
an inner boundary being discovered as client rendered which gets
upgraded to default.

<img width="1363" alt="Screenshot 2024-12-14 at 12 13 57 AM"
src="https://github.com/user-attachments/assets/a141133e-4856-4f38-a11f-f26bd00b6245"
/>
@sebmarkbage
Copy link
Collaborator Author

sebmarkbage commented Dec 14, 2024

I was also planning to add info in the details pane and the tooltip explaining more what this means.

One unfortunate thing is that the colors are different from the React DevTools profiler. Partly because we're limited in the colors we're allowed to use but also because we're showing more dimensions of data here.

  • Type of work (render, hydration, commit)
  • Size/impact of work (light, medium, dark)

@sebmarkbage sebmarkbage merged commit c32780e into facebook:main Dec 14, 2024
187 checks passed
github-actions bot pushed a commit that referenced this pull request Dec 14, 2024
Related to #31752.

When hydrating, we have two different ways of handling a Suspense
boundary that the server has already given up on and decided to client
render. If we have already hydrated the parent and then later this
happens, then we'll use the retry lane like any ping. If we discover
that it was already in client-render mode when we discover the Suspense
boundary for the first time, then schedule a default lane to let us
first finish the current render and then upgrade the priority to sync to
try to client render this boundary as soon as possible since we're
holding back content.

We used to use the `DefaultHydrationLane` for this but this is not
really a Hydration. It's actually a client render. If we get any other
updates flowing in from above at the same time we might as well do them
in the same pass instead of two passes. So this should be considered
more like any update.

This also means that visually the client render pass now gets painted as
a render instead of a hydration.

This show the flow of a shell being hydrated at the default priority,
then a Suspense boundary being discovered and hydrated at Idle and then
an inner boundary being discovered as client rendered which gets
upgraded to default.

<img width="1363" alt="Screenshot 2024-12-14 at 12 13 57 AM"
src="https://github.com/user-attachments/assets/a141133e-4856-4f38-a11f-f26bd00b6245"
/>

DiffTrain build for [d1dd7fe](d1dd7fe)
github-actions bot pushed a commit that referenced this pull request Dec 14, 2024
Related to #31752.

When hydrating, we have two different ways of handling a Suspense
boundary that the server has already given up on and decided to client
render. If we have already hydrated the parent and then later this
happens, then we'll use the retry lane like any ping. If we discover
that it was already in client-render mode when we discover the Suspense
boundary for the first time, then schedule a default lane to let us
first finish the current render and then upgrade the priority to sync to
try to client render this boundary as soon as possible since we're
holding back content.

We used to use the `DefaultHydrationLane` for this but this is not
really a Hydration. It's actually a client render. If we get any other
updates flowing in from above at the same time we might as well do them
in the same pass instead of two passes. So this should be considered
more like any update.

This also means that visually the client render pass now gets painted as
a render instead of a hydration.

This show the flow of a shell being hydrated at the default priority,
then a Suspense boundary being discovered and hydrated at Idle and then
an inner boundary being discovered as client rendered which gets
upgraded to default.

<img width="1363" alt="Screenshot 2024-12-14 at 12 13 57 AM"
src="https://github.com/user-attachments/assets/a141133e-4856-4f38-a11f-f26bd00b6245"
/>

DiffTrain build for [d1dd7fe](d1dd7fe)
sebmarkbage added a commit that referenced this pull request Dec 19, 2024
This is a follow up to #31752.

This keeps track in the commit phase whether this subtree was hydrated.
If it was, then we mark those components in the Components track as
green. Just like the phase itself is marked as green.

If the boundary client rendered we instead mark it as "errored" and its
children given the plain primary render color (blue). I also collect the
hydration error for this case so we can include its message in the
details view. (Unfortunately this doesn't support newlines atm.)

Most of the time this happens in separate commits for each boundary but
it is possible to force a client render in the same pass as a hydration.
Such as if an update flows into a boundary that has been put into
fallback state after it was initially attempted.

<img width="1487" alt="Screenshot 2024-12-18 at 12 06 54 AM"
src="https://github.com/user-attachments/assets/74c57291-4d11-414c-9751-3dac3285a89a"
/>
github-actions bot pushed a commit that referenced this pull request Dec 19, 2024
This is a follow up to #31752.

This keeps track in the commit phase whether this subtree was hydrated.
If it was, then we mark those components in the Components track as
green. Just like the phase itself is marked as green.

If the boundary client rendered we instead mark it as "errored" and its
children given the plain primary render color (blue). I also collect the
hydration error for this case so we can include its message in the
details view. (Unfortunately this doesn't support newlines atm.)

Most of the time this happens in separate commits for each boundary but
it is possible to force a client render in the same pass as a hydration.
Such as if an update flows into a boundary that has been put into
fallback state after it was initially attempted.

<img width="1487" alt="Screenshot 2024-12-18 at 12 06 54 AM"
src="https://github.com/user-attachments/assets/74c57291-4d11-414c-9751-3dac3285a89a"
/>

DiffTrain build for [17520b6](17520b6)
github-actions bot pushed a commit that referenced this pull request Dec 19, 2024
This is a follow up to #31752.

This keeps track in the commit phase whether this subtree was hydrated.
If it was, then we mark those components in the Components track as
green. Just like the phase itself is marked as green.

If the boundary client rendered we instead mark it as "errored" and its
children given the plain primary render color (blue). I also collect the
hydration error for this case so we can include its message in the
details view. (Unfortunately this doesn't support newlines atm.)

Most of the time this happens in separate commits for each boundary but
it is possible to force a client render in the same pass as a hydration.
Such as if an update flows into a boundary that has been put into
fallback state after it was initially attempted.

<img width="1487" alt="Screenshot 2024-12-18 at 12 06 54 AM"
src="https://github.com/user-attachments/assets/74c57291-4d11-414c-9751-3dac3285a89a"
/>

DiffTrain build for [17520b6](17520b6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants