mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-24 01:19:58 +00:00
fix: fix payload and use reviver to partially retrieve data
This commit is contained in:
parent
606a55f806
commit
b3087140ac
@ -91,47 +91,40 @@ export default defineComponent({
|
|||||||
key,
|
key,
|
||||||
...(import.meta.server && import.meta.prerender)
|
...(import.meta.server && import.meta.prerender)
|
||||||
? {}
|
? {}
|
||||||
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } }
|
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } },
|
||||||
|
result: {
|
||||||
|
chunks: result.chunks,
|
||||||
|
props: result.props,
|
||||||
|
teleports: result.teleports
|
||||||
|
}
|
||||||
},
|
},
|
||||||
...result
|
...result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ssrHTML = ref<string>('')
|
// needs to be non-reactive because we don't want to trigger re-renders
|
||||||
|
// at hydration, we only retrieve props/chunks/teleports from payload. See the reviver at nuxt\src\app\plugins\revive-payload.client.ts
|
||||||
if (import.meta.client) {
|
const rawPayload = toRaw(nuxtApp.payload.data)?.[`${props.name}_${hashId.value}`] ?? {}
|
||||||
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
|
const nonReactivePayload: Pick<NuxtIslandResponse, 'chunks'| 'props' | 'teleports'> = {
|
||||||
if (renderedHTML && nuxtApp.isHydrating) {
|
chunks: rawPayload.chunks,
|
||||||
setPayload(`${props.name}_${hashId.value}`, {
|
props: rawPayload.props,
|
||||||
html: getFragmentHTML(instance.vnode?.el ?? null, true).join(''),
|
teleports: rawPayload.teleports
|
||||||
state: {},
|
|
||||||
head: {
|
|
||||||
link: [],
|
|
||||||
style: []
|
|
||||||
},
|
|
||||||
chunks: {},
|
|
||||||
props: {},
|
|
||||||
teleports: {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ssrHTML.value = renderedHTML
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ssrHTML = ref<string>(getFragmentHTML(instance.vnode?.el ?? null).join(''))
|
||||||
|
|
||||||
const slotProps = computed(() => getSlotProps(ssrHTML.value))
|
const slotProps = computed(() => getSlotProps(ssrHTML.value))
|
||||||
const uid = ref<string>(ssrHTML.value.match(SSR_UID_RE)?.[1] ?? randomUUID())
|
const uid = ref<string>(ssrHTML.value.match(SSR_UID_RE)?.[1] ?? randomUUID())
|
||||||
const availableSlots = computed(() => [...ssrHTML.value.matchAll(SLOTNAME_RE)].map(m => m[1]))
|
const availableSlots = computed(() => [...ssrHTML.value.matchAll(SLOTNAME_RE)].map(m => m[1]))
|
||||||
|
|
||||||
// no need for reactivity
|
|
||||||
const interactivePayload: Pick<NuxtIslandResponse, 'chunks' | 'props' | 'teleports'> = import.meta.client && nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data)[`${props.name}_${hashId.value}_interactive`] : {}
|
|
||||||
|
|
||||||
const html = computed(() => {
|
const html = computed(() => {
|
||||||
const currentSlots = Object.keys(slots)
|
const currentSlots = Object.keys(slots)
|
||||||
let html = ssrHTML.value
|
let html = ssrHTML.value
|
||||||
|
|
||||||
if (import.meta.client && !canLoadClientComponent.value && Object.keys(interactivePayload.teleports).length) {
|
if (import.meta.client && !canLoadClientComponent.value && Object.keys(nonReactivePayload.teleports).length) {
|
||||||
for (const key in interactivePayload.teleports) {
|
for (const key in nonReactivePayload.teleports) {
|
||||||
html = html.replace(new RegExp(`<div [^>]*nuxt-ssr-client="${key}"[^>]*>`), (full) => {
|
html = html.replace(new RegExp(`<div [^>]*nuxt-ssr-client="${key}"[^>]*>`), (full) => {
|
||||||
return full + interactivePayload.teleports[key]
|
return full + nonReactivePayload.teleports[key]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +147,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
async function _fetchComponent (force = false) {
|
async function _fetchComponent (force = false) {
|
||||||
const key = `${props.name}_${hashId.value}`
|
const key = `${props.name}_${hashId.value}`
|
||||||
if (nuxtApp.payload.data[key] && !force) { return nuxtApp.payload.data[key] }
|
|
||||||
|
if (nuxtApp.payload.data[key]?.html && !force) { return nuxtApp.payload.data[key] }
|
||||||
|
|
||||||
const url = remoteComponentIslands && props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}`
|
const url = remoteComponentIslands && props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}`
|
||||||
|
|
||||||
@ -197,19 +191,14 @@ export default defineComponent({
|
|||||||
key.value++
|
key.value++
|
||||||
error.value = null
|
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 (import.meta.client) {
|
||||||
if (canLoadClientComponent.value) {
|
if (canLoadClientComponent.value) {
|
||||||
await loadComponents(props.source, res.chunks)
|
await loadComponents(props.source, res.chunks)
|
||||||
}
|
}
|
||||||
interactivePayload.props = res.props
|
nonReactivePayload.props = res.props
|
||||||
}
|
}
|
||||||
interactivePayload.teleports = res.teleports
|
nonReactivePayload.teleports = res.teleports
|
||||||
interactivePayload.chunks = res.chunks
|
nonReactivePayload.chunks = res.chunks
|
||||||
|
|
||||||
if (import.meta.client) {
|
if (import.meta.client) {
|
||||||
// must await next tick for Teleport to work correctly with static node re-rendering
|
// must await next tick for Teleport to work correctly with static node re-rendering
|
||||||
@ -237,7 +226,7 @@ export default defineComponent({
|
|||||||
} else if (import.meta.server || !nuxtApp.isHydrating) {
|
} else if (import.meta.server || !nuxtApp.isHydrating) {
|
||||||
await fetchComponent()
|
await fetchComponent()
|
||||||
} else if (nuxtApp.isHydrating && canLoadClientComponent.value) {
|
} else if (nuxtApp.isHydrating && canLoadClientComponent.value) {
|
||||||
await loadComponents(props.source, interactivePayload.chunks)
|
await loadComponents(props.source, nonReactivePayload.chunks)
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -258,14 +247,14 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
for (const [id, html] of Object.entries(interactivePayload.teleports)) {
|
for (const [id, html] of Object.entries(nonReactivePayload.teleports)) {
|
||||||
nodes.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
|
nodes.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
|
||||||
default: () => [createStaticVNode(html, 1)]
|
default: () => [createStaticVNode(html, 1)]
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (import.meta.client && canLoadClientComponent.value && html.value.includes('nuxt-ssr-client')) {
|
if (import.meta.client && canLoadClientComponent.value && html.value.includes('nuxt-ssr-client')) {
|
||||||
for (const [id, props] of Object.entries(interactivePayload.props)) {
|
for (const [id, props] of Object.entries(nonReactivePayload.props)) {
|
||||||
// @ts-expect-error _ is the component's default export in build chunks
|
// @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 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}"]` }, {
|
const vnode = createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-client="${id}"]` }, {
|
||||||
|
@ -17,7 +17,7 @@ const revivers: Record<string, (data: any) => any> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (componentIslands) {
|
if (componentIslands) {
|
||||||
revivers.Island = ({ key, params }: any) => {
|
revivers.Island = ({ key, params, result }: any) => {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (!nuxtApp.isHydrating) {
|
if (!nuxtApp.isHydrating) {
|
||||||
nuxtApp.payload.data[key] = nuxtApp.payload.data[key] || $fetch(`/__nuxt_island/${key}`, {
|
nuxtApp.payload.data[key] = nuxtApp.payload.data[key] || $fetch(`/__nuxt_island/${key}`, {
|
||||||
@ -28,7 +28,15 @@ if (componentIslands) {
|
|||||||
return r
|
return r
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return null
|
return {
|
||||||
|
html: '',
|
||||||
|
state: {},
|
||||||
|
head: {
|
||||||
|
link: [],
|
||||||
|
style: []
|
||||||
|
},
|
||||||
|
...result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user