Під час гідрації Vue очікує, що DOM, отриманий із сервера, точно відповідає тому, що відрендерив би клієнт з тими самими даними. Якщо ні - у консолі Hydration mismatch, а Vue виправляє розбіжність, перебудовуючи частину DOM. Це повільно, а в продакшені може лишити неправильний вміст.
Типові причини:
1. Дані, що відрізняються на сервері й клієнті:
<span>{{ new Date().toLocaleTimeString() }}</span> <!-- час сервера ≠ час браузера -->
<span>{{ Math.random() }}</span>
<p>{{ formatDate(order.createdAt) }}</p> <!-- різні часові пояси -->
2. Код, що залежить від браузера:
<div v-if="window.innerWidth > 768">...</div> <!-- на сервері window немає -->
<p>{{ localStorage.getItem('name') }}</p>
3. Невалідна вкладеність HTML. <div> всередині <p>, <tr> без <tbody> - браузер «виправляє» розмітку при розборі, і DOM уже не відповідає серверному HTML.
4. Сторонні скрипти й розширення браузера, що змінюють DOM до гідрації.
5. Генеровані id, які на сервері й клієнті виходять різними (лічильник, Math.random()).
Як виправляти:
- значення, що мають бути лише на клієнті, - встановлювати в
onMounted(він не виконується на сервері):
const now = ref<string | null>(null)
onMounted(() => { now.value = new Date().toLocaleTimeString() })
- детерміновані дані: форматування дат з явним часовим поясом (
Intl.DateTimeFormat('uk', { timeZone: 'Europe/Kyiv' })), а не поясом середовища; useId()(Vue 3.5) для id, стабільних між сервером і клієнтом;- клієнтські компоненти - рендерити лише в браузері (
<ClientOnly>у Nuxt чи власна обгортка з прапорцем, встановленим вonMounted); - валідна розмітка - перевіряється валідатором HTML.
Свідома розбіжність. Якщо значення має відрізнятися (час, локальна дата), Vue 3.5 дозволяє придушити попередження атрибутом:
<span data-allow-mismatch="text">{{ localTime }}</span>
Значення атрибута обмежує тип розбіжності: text, children, class, style, attribute. Це для точкових випадків, а не спосіб приховати справжні баги.
Діагностика: у режимі розробки попередження показує, який саме вузол не збігся. Для продакшен-збірки детальні повідомлення вмикаються прапорцем __VUE_PROD_HYDRATION_MISMATCH_DETAILS__.