Un error de hidratación ocurre cuando el HTML que renderiza el cliente difiere del que envió el servidor. Vue intenta recuperarse descartando los nodos que no coinciden y re-renderizándolos, lo que provoca parpadeos, pérdida de rendimiento y manejadores de eventos rotos.
Causas habituales
1. HTML anidado no válido. Los navegadores corrigen automáticamente el marcado inválido antes de que Vue lo vea.
<template>
<!-- El navegador lo divide en <p></p><div>...</div><p></p> -->
<p>
<div>Esto rompe la hidratación</div>
</p>
</template>2. Valores no deterministas en el render. Math.random(), Date.now() y new Date().toLocaleString() producen resultados distintos en el servidor y en el cliente.
<template>
<!-- Servidor: "field-0.847..." / Cliente: "field-0.231..." -->
<input :id="'field-' + Math.random()" />
<!-- La zona horaria del servidor != zona horaria del cliente -->
<span>{{ new Date().toLocaleTimeString() }}</span>
</template>Solución: aplaza los valores no deterministas a onMounted.
const fieldId = ref('field-default')
const displayTime = ref('')
onMounted(() => {
fieldId.value = 'field-' + crypto.randomUUID()
displayTime.value = new Date().toLocaleTimeString()
})3. Extensiones del navegador que inyectan contenido. Extensiones como bloqueadores de anuncios o gestores de contraseñas modifican el DOM entre la llegada del HTML del servidor y el inicio de la hidratación de Vue.
Suprimir discrepancias intencionadas (Vue 3.5+)
Usa data-allow-mismatch cuando la diferencia es esperada:
<template>
<span data-allow-mismatch="text">
{{ clientOnlyTimestamp }}
</span>
</template>Valores aceptados: text, children, class, style, attribute, o sin valor (suprime todos).
Depuración
Activa los avisos detallados en vite.config.ts:
export default defineConfig({
define: {
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true
}
})| Mensaje de error | Causa probable |
|---|---|
| "Hydration text content mismatch" | Fechas, valores aleatorios, diferencias de zona horaria |
| "Hydration children mismatch" | HTML anidado inválido, renderizado condicional |
| "Hydration node mismatch" | Se renderiza un elemento completamente distinto |