How to avoid hydration missmatch when using a dynamic template?

Hello, I'm working on a project where we fetch page data from a CMS as html. It can contain vue components such as a Tooltips. It basically works after turning on runtimeCompiler in nuxt.config but I get a lot of hydration mismatches from it. Does anyone have any tips on how to fix this? This is the component code:
import { h } from 'vue';
import Tooltip from '~/components/OTooltip.vue';

export default {
props: {
content: {
type: String,
required: true,
},
},
setup(props) {
const renderContent = {
components: {
Tooltip,
},
template: `<div class="article__body">${props.content}</div>`,
};
return () => {
return h(renderContent);
};
},
};
</script>
import { h } from 'vue';
import Tooltip from '~/components/OTooltip.vue';

export default {
props: {
content: {
type: String,
required: true,
},
},
setup(props) {
const renderContent = {
components: {
Tooltip,
},
template: `<div class="article__body">${props.content}</div>`,
};
return () => {
return h(renderContent);
};
},
};
</script>
2 Replies
kapa.ai
kapa.ai2w ago
Hi @Liek2Saev. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Hydration mismatches in Nuxt often occur when the HTML rendered on the server does not match what is rendered on the client during hydration. This is especially common when using dynamic templates or rendering HTML content fetched from a CMS, as the server and client may process or interpret the content differently, or the content may include client-only Vue components that are not available or rendered the same way on the server. Key points and recommendations from the knowledge sources: 1. Avoid Mutating Props or Shared Data
If you mutate props or shared data in your component (for example, by modifying the content string or its structure), you can cause mismatches between server and client renders. Always work with a local copy if you need to modify data, as mutating props directly can lead to hydration issues. This is highlighted in the context of array mutation, but the principle applies to any prop or shared data mutation Nuxt 3 Hydration text mismatch in ... error when using shift(). 2. Client-Only Rendering for Dynamic Content
If your dynamic template includes components or logic that cannot be reliably rendered on the server (for example, components registered at runtime or content that depends on browser APIs), consider wrapping the rendered content in a <client-only> tag. This ensures that the content is only rendered on the client, avoiding SSR/client mismatches Handling simple hydration mismatch after fetch in Nuxt 3.
<template>
<client-only>
<component :is="renderContent" />
</client-only>
</template>

<template>
<client-only>
<component :is="renderContent" />
</client-only>
</template>

3. SSR Limitations with Runtime Templates
Using the runtime template compiler (runtimeCompiler: true) can introduce hydration issues, especially if the template or its components are not available or rendered identically on both server and client. Nuxt's SSR expects the same output on both sides. If your CMS content includes dynamic Vue components, SSR may not be able to process them the same way as the client, leading to mismatches. 4. Consider Client-Side Rendering for the Page or Section
If hydration mismatches persist and the content is highly dynamic or client-specific, you can disable SSR for the route or component using Nuxt's routeRules or by wrapping the section in <client-only>. This will render the content only on the client, avoiding SSR mismatches Handling simple hydration mismatch after fetch in Nuxt 3.
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/your-dynamic-page': { ssr: false }
}
})

// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/your-dynamic-page': { ssr: false }
}
})

Summary:
Hydration mismatches with dynamic templates and runtime-compiled content are a known challenge in Nuxt. The most reliable solution is to render such content only on the client using <client-only>, or to disable SSR for the affected route. Avoid mutating props or shared data, and be aware that SSR cannot always process runtime templates or dynamic component registration the same way as the client. If you need more granular control, consider restructuring your CMS content to separate static HTML from dynamic Vue components, and render the dynamic parts client-side only. For more details, see the discussion on hydration mismatches and client-only rendering in the Nuxt documentation and community Q&A Nuxt 3 Hydration text mismatch in ... error when using shift() Handling simple hydration mismatch after fetch in Nuxt 3. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@252030467040083979> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?