Conrad Nuxt

Rendering and hydration

What happens from a request to an interactive Nuxt page, what the payload carries, why plain $fetch in setup causes double requests, hydration mismatches and how to find them, SSR trade-offs with per-route rendering, and tree-shaking.

From the SSR, hydration and tree-shaking parts of your Nuxt note.

Know

  • The flow: Nitro creates a Nuxt app per request, renders to HTML while waiting for useFetch and useAsyncData, embeds the payload (fetched data, useState, public runtime config, errors); the browser shows the HTML, loads the JavaScript from the CDN, and Vue hydrates the existing DOM using the payload.
  • $fetch in setup: runs on the server and again in the browser, result not in the payload; use useFetch/useAsyncData for data the page renders, $fetch in handlers, onMounted and server code.
  • Mismatches: caused by values that differ between runs, browser-only state, double fetching, invalid HTML, extensions. Development warns; production patches the client version over the server one. Find them with the warning, the payload in DevTools and <ClientOnly>; Vue 3.5 adds data-allow-mismatch for values allowed to differ.
  • SSR trade-offs: SEO and a fast first paint versus server cost, no browser APIs during render, per-request state and the hydration cost.
  • Route rules: prerender, swr/isr, ssr: false per path, so one app mixes static, cached and client-only pages.
  • Nitro: the server engine under Nuxt; presets build the same server for Node, Cloudflare Workers, Vercel and others; useStorage mounts a driver (memory, fs, Redis, KV) per environment; Nuxt 5 moves to Nitro 3.
  • Tree-shaking: unused ES module exports are dropped from the bundle; needs side-effect-free modules.

Fact check of your notes

Gotcha· Vue has always repaired mismatches in production; it is not free

"Vue 3.4+ solves hydration errors in prod by brute forcing the client DOM": Vue recovers from mismatches in production by patching the mismatched nodes to the client version, and has done so since Vue 3. What 3.4 added is clearer warnings and the __VUE_PROD_HYDRATION_MISMATCH_DETAILS__ flag to keep them in production builds; 3.5 added data-allow-mismatch. The repair throws away the server render for that part and can flicker, so mismatches are still bugs.

Exercise

Exercise
  • In a small Nuxt app, load data once with $fetch in setup and once with useFetch, open the network panel on a full reload and compare the requests; then find the data in the payload in DevTools.
  • Create a mismatch on purpose with Date.now() in a template, read the warning, and fix it twice: with useState and with <ClientOnly>.

Be able to say

Be able to say· What causes hydration mismatches and how do you fix them?

"The server and the client rendered different things. Usually it's a value that differs between the two runs, like a date or a random id, something only the browser knows, like localStorage or the window size, data fetched with plain $fetch so the client fetches again, or invalid HTML the browser repaired. I read the warning, check the payload in DevTools and wrap suspects in <ClientOnly> to narrow it down. The fix is to make the value the same on both sides, usually through useState or useFetch, or to render the browser-only part after mounting."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.