Search code examples
reactjsgoogle-chrome-devtoolsnext.jslighthousecore-web-vitals

Next.js-before-hydration, Next.js-hydration, and FCP


I was wondering if someone could explain what the timing metrics Next.js-before-hydration and Next.js-hydration mean, and how they relate to FCP. This is for a NextJS app that server-side-renders and uses hooks on the client side.

Here is a screenshot of a Performance tab measurement, which is of a fresh page load that will hit the react server and SSR. This particular page has components that also re-render a number of times on the client side before the page settles out. I've zoomed in to the area starting at the initial request, and including initial core web vitals like FCP and LCP. (TTI and TTFB are much later off screen.)

enter image description here

It appears that Next.js-before-hydration starts exactly when the server request starts. (The filmstrip appears to show thumbnails from the page that was previously in the browser, which seems like a devtools bug, so ignore that.)

Next.js-before-hydration lasts 1.48s in this example, but for this request, TTFB was only 120ms, so I know it includes more than server response time.

I know that FCP is "TTFB + content load time + render time", so I thought that Next.js-before-hydration must be a subset of that, but I've seen examples of other sites (ticketmaster.com is an example) where the end of Next.js-before-hydration extends far beyond FP/FCP and where Next.js-hydration ends even later - sometimes just before the onLoad event (the red L).

Going by the film strip, content is starting to display progressively before we get to Next.js-hydration (labeled as Next.js...dration in the image), which makes me think that it's already starting to run hooks and re-render.

So what does it mean when NextJS transitions from Next.js-before-hydration to Next.js-hydration? Does it have to do with when the "first" render finishes (meaning the first time each component is loaded, like the first render in React Profiler), and when the hooks start to run?

Finally, what does the end of Next.js-hydration mean, and how do these two metrics relate to FCP?


Solution

  • After a few more weeks of learning and investigation, I think the answer is basically -

    FCP has little to no direct relationship with Next.js-hydration or Next.js-before-hydration.

    Part of this is a conflation of definitions of the word "render".

    It is true that FCP is "TTFB + content load time + render time". But in this context, "render" has nothing to do with the React definitions of "render". In this context, "render" is more about the html rendering stage that happens before paint. And many browsers may try to paint elements to the screen, even before Dom content has finished loading (and perhaps even before domInteractive, I'm not sure about that).

    So, sometimes FCP may happen before Next.js-before-hydration is complete, and in other cases, it may not happen until later. In the question's example, the performance measurement is in dev mode, which may be delaying FCP.

    As for the difference between Next.js-before-hydration and Next.js-hydration, the insight to remember there is that hydration is not even possible until all the necessary react libraries are loaded.

    This means that Next.js-before-hydration, by definition, includes:

    • The time spent to download the initial html (which includes TTFB)
    • The time spent to parse the initial html up through the necessary script tags that load the react libs
    • The time spent to download those critical javascript chunk files
    • The time spent to evaluate/execute those javascript chunk files, and load the react environment.

    It's only at that point that the react hydration process can start. I believe the react hydration process is then about processing React render #1, and attaching the react event model to all the components that are part of that first render.

    It's only after Next.js-hydration completes that reconciliation (additional commits/renders) becomes possible.