= import.meta.client && nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data)[`${props.name}_${hashId.value}_interactive`] : {}
+
const html = computed(() => {
const currentSlots = Object.keys(slots)
- const html = ssrHTML.value
+ let html = ssrHTML.value
+
+ if (import.meta.client && !canLoadClientComponent.value && Object.keys(interactivePayload.teleports).length) {
+ for (const key in interactivePayload.teleports) {
+ html = html.replace(new RegExp(`]*nuxt-ssr-client="${key}"[^>]*>`), (full) => {
+ return full + interactivePayload.teleports[key]
+ })
+ }
+ }
return html.replace(SLOT_FALLBACK_RE, (full, slotName, content) => {
// remove fallback to insert slots
@@ -128,6 +144,7 @@ export default defineComponent({
return content
})
})
+
function setUid () {
uid.value = ssrHTML.value.match(SSR_UID_RE)?.[1] ?? getId() as string
}
@@ -162,7 +179,7 @@ export default defineComponent({
setPayload(key, result)
return result
}
- const key = ref(0)
+
async function fetchComponent (force = false) {
nuxtApp[pKey] = nuxtApp[pKey] || {}
if (!nuxtApp[pKey][uid.value]) {
@@ -179,21 +196,25 @@ export default defineComponent({
})
key.value++
error.value = null
+
+ nuxtApp.payload.data[`${props.name}_${hashId.value}_interactive`] = {
+ chunks: res.chunks,
+ props: res.props,
+ teleports: res.teleports
+ }
+ if (import.meta.client) {
+ if (canLoadClientComponent.value) {
+ await loadComponents(props.source, res.chunks)
+ }
+ interactivePayload.props = res.props
+ }
+ interactivePayload.teleports = res.teleports
+ interactivePayload.chunks = res.chunks
+
if (import.meta.client) {
// must await next tick for Teleport to work correctly with static node re-rendering
await nextTick()
}
- nuxtApp.payload.data[`${props.name}_${hashId.value}_interactive`] = {
- chunks: res.chunks,
- props: res.props
- }
-
- if (import.meta.client) {
- await loadComponents(props.source, res.chunks)
- interactiveProps = res.props
- } else {
- interactiveTeleports = res.teleports || {}
- }
setUid()
} catch (e) {
@@ -215,8 +236,8 @@ export default defineComponent({
fetchComponent()
} else if (import.meta.server || !nuxtApp.isHydrating) {
await fetchComponent()
- } else if (nuxtApp.isHydrating) {
- await loadComponents(props.source, interactiveChunksList)
+ } else if (nuxtApp.isHydrating && canLoadClientComponent.value) {
+ await loadComponents(props.source, interactivePayload.chunks)
}
return () => {
@@ -237,14 +258,14 @@ export default defineComponent({
}
}
if (import.meta.server) {
- for (const [id, html] of Object.entries(interactiveTeleports)) {
+ for (const [id, html] of Object.entries(interactivePayload.teleports)) {
nodes.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
default: () => [createStaticVNode(html, 1)]
}))
}
}
- if (import.meta.client && html.value.includes('nuxt-ssr-client')) {
- for (const [id, props] of Object.entries(interactiveProps)) {
+ if (import.meta.client && canLoadClientComponent.value && html.value.includes('nuxt-ssr-client')) {
+ for (const [id, props] of Object.entries(interactivePayload.props)) {
// @ts-expect-error _ is the component's default export in build chunks
const component = components!.get(id.split('-')[0])!._ ?? components!.get(id.split('-')[0])!
const vnode = createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-client="${id}"]` }, {
diff --git a/test/fixtures/basic/components/AsyncServerComponent.server.vue b/test/fixtures/basic/components/AsyncServerComponent.server.vue
index 63318e5f09..c3a7abc49b 100644
--- a/test/fixtures/basic/components/AsyncServerComponent.server.vue
+++ b/test/fixtures/basic/components/AsyncServerComponent.server.vue
@@ -6,12 +6,13 @@
{{ count }}
-
+
+
The component bellow is not a slot but declared as interactive
-
-
+
+
-
+