Short Answer
There is no reconciliation priority: Nuxt does not arbitrate between a Server Component (island) and a parent hydrated component when their DOM disagrees. Islands hydrate independently from their own serialized props, while the surrounding page hydrates against the SSR HTML. When Vue reports a hydration node mismatch, it means the server-rendered markup and the client's first render produced different nodes at that position — and Vue patches forward rather than "reconciling" the island. The fix is therefore not about priority but about removing the source of divergence: non-deterministic output, invalid HTML nesting, or unstable props/keys.
Likely Causes, Ranked
Likely explanation (not confirmed for your case): the mismatch comes from one of these, in rough order of frequency:
- Non-deterministic render output —
Date.now(), Math.random(), locale/timezone-dependent formatting, or values derived from window/navigator evaluated during render. The server and client compute different strings, so the text node or attribute differs.
- Invalid HTML nesting — a
<div> inside a <p>, a missing <tbody> in a <table>, or interactive elements nested inside links/buttons. The browser repairs the markup before hydration, so the client hydrates against a DOM that no longer matches what the server sent.
- Unstable keys or props on the island — index-based
:key in v-for, or props that are not serializable/stable (functions, class instances, un-normalized Dates). The island then hydrates against different content than it rendered.
- External DOM mutation — browser extensions, ad blockers, or third-party scripts injecting attributes into the SSR HTML before hydration runs.
What To Do
Keep Server Components pure and deterministic. Anything browser-only goes behind <ClientOnly> or into onMounted, never in the render path:
<template>
<div>
<ServerClock />
<ClientOnly>
<UserTimezoneWidget />
</ClientOnly>
</div>
</template>
For data that must render on the server but varies (timestamps, random IDs), generate it once and pass it through the payload so both sides see the identical value — for example via useState or a prop serialized into the island's payload — rather than recomputing it on the client. Normalize Dates to ISO strings before they cross the boundary.
Use stable, content-derived keys in lists, and avoid toggling wrapper elements around the island between server and client renders.
Verifying the Actual Cause
Do not suppress hydration warnings globally — that hides the divergence and can surface later as broken event binding. Instead:
- Reproduce in a clean browser profile (extensions off) to rule out injected attributes.
- Read the hydration warning: it names the failing node. Compare View Source (the raw SSR HTML) with the post-load DOM in DevTools around that node. Browser-repaired nesting shows up here immediately.
- Temporarily replace dynamic values with constants. When the warning disappears, reintroduce one change at a time.
- If the mismatch is data-dependent, log the island's props on both sides and confirm they are identical, including key ordering.
On Payload Size
Serializing a value once into window.__NUXT__ and reusing it is cheaper than the alternative — a mismatch that forces client-side re-rendering or duplicate fetches. The payload cost is proportional to what you serialize, so serialize only the fields the island actually renders, not whole API responses.
Version caveat: island behavior and payload internals are version-sensitive in Nuxt 3. Confirm your exact Nuxt and Vue versions before treating any specific warning text or API as definitive, and check the release notes if behavior changed after an upgrade.