v-text and v-html and may be other built-in (custom may be too) directives on custom component with slot in SSR
Vue version
3
Link to minimal reproduction
Vue 3 https://stackblitz.com/edit/github-lf1exv?terminal=dev
Nuxt 3 https://github.com/max5432112345/nuxt-error-2/
Steps to reproduce
If use v-text on custom component with slot when in SPA text is displayed in page but in SSR not displayed (hot reload only sometime make it to display but after refresh page disappear).
Index.vue
<template>
<div>
<CustomText v-text="'test'" />
<CustomText> TEST </CustomText>
</div>
</template>
CustomText.vue
<template>
<span>
<slot name="default" />
</span>
</template>
What is expected?
We certainly want behaviour similar on SSR vs SPA when using v-text
What is actually happening?
In vue 2 it produced early warnings (Hydration children mismatch) when used v-text without inner text (and I add $nbsp; to bypass that) but now no errors or warnings. Now in vue 3 it not permit to use inner text and v-text together.
In that situation it not show errors or warnings like vue 2:
System Info
vue 3
linux
Any additional comments?
The root cause is that directives with children overwrite (e.g. v-html & v-text) are not working with Component yet in SSR. here is a workaround
My use case:
I want to create a JSON-LD script tag with metadata. I want to use data passed to a component as props.
No workaround is available for this AFAIK.
Here is my workaround:
/**
* This is similar to `component(:is="tag")`, except that it also works in SSR.
*
* See:
* - https://discord.com/channels/473401852243869706/1152225826910244955/1152225826910244955
* - https://stackblitz.com/edit/github-gs1ptn
* - https://github.com/vuejs/core/issues/6553#issuecomment-1232468857
* - https://github.com/vuejs/core/issues/6435
* - https://play.vuejs.org/#__SSR__eNp9UctOwzAQ/BXLl7RSlR64hbQSVJUA8RL0hjlEybZ1SWzLXpdIVf4dP5ISJMCHaDM7O57xnuiVUunRAs1ojtCoukBYMkFIXvFjKFy5sgZls4EWSYbuu2A0QTCYMErmkT2P9Hw+EslNqblCYgCtcv+8UVIjGalttWxIks5XsgkuEq8Qp5Z0RgfYm+vRs8qJ7EnXC8RJaEOjgm1ha0fwvpSWymRvzm2LyfvMQ8HNJDSmkUSIdpgWZDIliz4zIftJ4jIls4HjDxcC9M3m4T6LyqnXDar+dNNLX3YO6H4GQVNKseW79GCkcGmCJKOly8dr0E8KuRSG0Wy4jNGiruXnXcBQW+gvcTN7KD9+wQ+m9RijzxoM6CMweu5hoXeAsb1+fXSeR81GVrZ27H+aL2Bkbb3HSLu2onK2R7zg9jZshovdxqxbBGGGUN7o8DKe7fblV/tX9G+7F+lFmHMPSrsvfIzfCg==
*/
export default defineComponent({
props: {
tag: {
type: String,
required: true,
},
html: {
type: String,
required: true,
},
},
setup(props, { slots }) {
return () => h(props.tag, { innerHTML: props.html });
},
});