Merge branch 'refactor/nuxt-island' of https://github.com/nuxt/nuxt into refactor/nuxt-island

This commit is contained in:
julien huang 2023-12-29 22:41:14 +01:00
commit 183393247d
3 changed files with 12 additions and 16 deletions

View File

@ -85,12 +85,6 @@ export default defineComponent({
// If not hydrating, fetchComponent() will set it // If not hydrating, fetchComponent() will set it
const rawPayload = nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data)?.[`${props.name}_${hashId.value}`] ?? emptyPayload() : emptyPayload() const rawPayload = nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data)?.[`${props.name}_${hashId.value}`] ?? emptyPayload() : emptyPayload()
const nonReactivePayload: Pick<NuxtIslandResponse, 'chunks'| 'props' | 'teleports'> = {
chunks: rawPayload.chunks,
props: rawPayload.props,
teleports: rawPayload.teleports
}
const ssrHTML = ref<string>(getFragmentHTML(instance.vnode?.el ?? null, true)?.join('') || '') const ssrHTML = ref<string>(getFragmentHTML(instance.vnode?.el ?? null, true)?.join('') || '')
const slotProps = computed(() => getSlotProps(ssrHTML.value)) const slotProps = computed(() => getSlotProps(ssrHTML.value))
@ -103,8 +97,7 @@ export default defineComponent({
let html = ssrHTML.value let html = ssrHTML.value
if (!canLoadClientComponent.value) { if (!canLoadClientComponent.value) {
// replace all client components with their static content for (const [key, value] of Object.entries(rawPayload.teleports || {})) {
for (const [key, value] of Object.entries(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 + value return full + value
}) })
@ -168,10 +161,10 @@ export default defineComponent({
if (canLoadClientComponent.value && res.chunks) { if (canLoadClientComponent.value && res.chunks) {
await loadComponents(props.source, res.chunks) await loadComponents(props.source, res.chunks)
} }
nonReactivePayload.props = res.props rawPayload.props = res.props
} }
nonReactivePayload.teleports = res.teleports rawPayload.teleports = res.teleports
nonReactivePayload.chunks = res.chunks rawPayload.chunks = res.chunks
// must await next tick for Teleport to work correctly so vue can teleport the content to the new static node // must await next tick for Teleport to work correctly so vue can teleport the content to the new static node
// teleport update is based on uid // teleport update is based on uid
@ -199,8 +192,8 @@ export default defineComponent({
fetchComponent() fetchComponent()
} else if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered) { } else if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered) {
await fetchComponent() await fetchComponent()
} else if (selectiveClient && canLoadClientComponent.value && nonReactivePayload.chunks) { } else if (selectiveClient && canLoadClientComponent.value && rawPayload.chunks) {
await loadComponents(props.source, nonReactivePayload.chunks) await loadComponents(props.source, rawPayload.chunks)
} }
return () => { return () => {
@ -213,6 +206,7 @@ export default defineComponent({
}, [h(createStaticVNode(html.value || '<div></div>', 1))])] }, [h(createStaticVNode(html.value || '<div></div>', 1))])]
if (uid.value && (mounted.value || nuxtApp.isHydrating) && html.value) { if (uid.value && (mounted.value || nuxtApp.isHydrating) && html.value) {
// render slots
for (const slot in slots) { for (const slot in slots) {
if (availableSlots.value.includes(slot)) { if (availableSlots.value.includes(slot)) {
nodes.push(createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` }, { nodes.push(createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` }, {
@ -220,8 +214,10 @@ export default defineComponent({
})) }))
} }
} }
// render components
if (selectiveClient && canLoadClientComponent.value) { if (selectiveClient && canLoadClientComponent.value) {
for (const [id, props] of Object.entries(nonReactivePayload.props ?? {})) { for (const [id, props] of Object.entries(rawPayload.props ?? {})) {
const component = components!.get(id.split('-')[0])! const component = 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}"]` }, {
default: () => { default: () => {

View File

@ -9,7 +9,7 @@ import { joinURL, withQuery } from 'ufo'
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer' import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
import { useNuxtApp, useRuntimeConfig } from '../nuxt' import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { prerenderRoutes, useRequestEvent } from '../composables/ssr' import { prerenderRoutes, useRequestEvent } from '../composables/ssr'
import { SLOTNAME_RE, SSR_UID_RE, UID_ATTR, getSlotProps, nuxtIslandProps, pKey } from './utils' import { SLOTNAME_RE, SSR_UID_RE, UID_ATTR, getSlotProps, pKey, nuxtIslandProps } from './utils'
// @ts-expect-error virtual file // @ts-expect-error virtual file
import { remoteComponentIslands, selectiveClient } from '#build/nuxt.config.mjs' import { remoteComponentIslands, selectiveClient } from '#build/nuxt.config.mjs'