I have a Nuxt 3 application that gets page content from an external CMS via GraphQL. The content that I get is totally dynamic, so I have to use dynamic components to render my content.
For example if I query getContentFromPath
with the paramter {path: '/'}
it would return something like this:
getContentFromPath: {
id: 'abc123',
dynamicContent: [
{
id: 'xyz123',
cmsComponent: 'RichText',
data: 'here would be richtext specific data like some html'
}
]
}
So based on what the content manager maintained in the CMS, the content that I query could change. It could be different components like RichText, Image and so on.
Therefore I have a generic Nuxt page [...pages].vue
where all my routes get handled.
I am using apollo to get my data like so (simplified):
<script setup>
import { useQuery } from '@vue/apollo-composable';
import { getContentFromPath } from './graphql/queries';
const cmsComponent = ref('');
const contentFromPath = await useQuery(getContentFromPath, {
path: '/',
});
contentFromPath.onResult((res) => (cmsComponent.value = res.data.getContentFromPath.dynamicContent[0].cmsComponent));
</script>
<template>
<component :is="cmsComponent" />
</template>
Here I am facing the hydration problem. I have to wait for my CMS content to be returned to my Nuxt application. Then I know which components to render. The components could also query data (e.g. a blog-list-component). The Nuxt server part queries the data but the client doesn't know about this and rerenders / rehydrates as soon as everything is loaded.
With more complex components from the CMS it can happen, that the page flashes because some components get rerendered faster. Using <client-only>
is not an option because the content inside these components are relevant for SEO. What I am searching for is a solution that gets the data on the server side, prepares all the components and then renders it on the client side.
So my questions are: How do I deal with hydration in my case? Is it even possible or is Nuxt the wrong Framework for my use-case?
P.S. I already read the article from Alexander Lichter https://blog.lichter.io/posts/vue-hydration-error/
If something isn't clear, please let me know.