[Lv2] Nuxt 3 Lifecycle and Hydration Fundamentals
Understanding lifecycle boundaries and hydration behavior is key to avoiding SSR-client mismatch issues.
1. Interview focus
- Server-side vs client-side lifecycle differences
useStatevsrefin SSR- Typical hydration mismatch causes and fixes
2. Lifecycle boundaries in Nuxt 3
In SSR mode:
setup()runs on server and clientonMounted()runs only on client- Browser APIs must be guarded for client execution
<script setup lang="ts">
if (process.server) {
console.log('Server render phase');
}
onMounted(() => {
// Client only
console.log(window.location.href);
});
</script>
3. Why hydration mismatch happens
Common causes:
- Rendering random values (
Math.random()) during SSR - Rendering time-dependent values (
new Date()) without synchronization - Accessing browser-only APIs during server render
- Different conditional branches between server and client
4. useState vs ref in SSR
refis local reactive state for component instanceuseStateserializes and hydrates state across SSR boundary
const counter = useState<number>('counter', () => 0);
For shared SSR-aware state, prefer useState.
5. Practical mismatch prevention
- Wrap browser-only UI with
ClientOnlywhen needed - Move browser APIs to
onMounted - Ensure deterministic initial render values
- Keep SSR and client branching explicit (
process.server,process.client)
6. Debug workflow
- Reproduce mismatch on full page refresh
- Compare server HTML and hydrated DOM
- Disable suspicious dynamic fragments incrementally
- Confirm final render stability under slow network and cold load
Interview-ready summary
I treat SSR and client as two execution phases. I keep initial output deterministic, use
useStatefor SSR-shared state, and isolate browser-only logic to client hooks. This prevents hydration mismatch and keeps rendering predictable.