Hydration Mismatches

Identify hydration mismatches in Vue/VitePress in the production build!

Here’s my little rant on how I tracked down the exact changes when this popped up 👉 Hydration completed but contains mismatches.

Debugging hydration mismatches is tricky because these only show up in production builds with obfuscated JavaScript files. Here’s a breakdown of what I went down to find and fix this issue.

I searched Google and ChatGPT for answers but came up empty. Even after scanning recent PRs (there were quite a few, uff!), I had no luck. So, I went old-school: manually commenting out changes one by one until I finally found the culprit.

QUICK HEADS UP 🚨

I use prettier to format my projects, which also takes care of formatting *.vue files.

Long story short, I eventually found this vue configuration option. After checking the source and types, I stumbled upon this gem:

TypeScript
vue: {
    features: {
        // Only use this when debugging!
        prodHydrationMismatchDetails: true
    }
}

OKAY, WHAT DOES THIS DO?

This option shows the server-client rendering differences in DEV TOOLS > CONSOLE, making it easier to spot and fix issues.

My Issue with Prettier

In my case, I was using this code :

Vue
<button class="close-btn" @click="() => (showModal = false)">✕</button>

So, when Prettier formatted the code, it ended up like this :

Vue
<button
    class="close-btn"
    @click="() => (showModal = false)"
>
    ✕
</button>

This extra space caused a mismatch in the rendered content, resulting in an error. My fix was simple—I replaced the code with this :

Vue
<button
    v-text="'✕'"
    class="close-btn"
    @click="() => (showModal = false)"
/>

One tiny space 🤏, one giant headache. Who knew debugging could be so… precise? 😅