Skip to content

Commit

Permalink
perf(nuxt): reduce nuxt island payload (#26569)
Browse files Browse the repository at this point in the history
  • Loading branch information
huang-julien committed Mar 30, 2024
1 parent 41ab124 commit 6dcad76
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 33 deletions.
63 changes: 35 additions & 28 deletions packages/nuxt/src/app/components/nuxt-island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,32 @@ export default defineComponent({
onMounted(() => { mounted.value = true; teleportKey.value++ })

function setPayload (key: string, result: NuxtIslandResponse) {
const toRevive: Partial<NuxtIslandResponse> = {}
if (result.props) { toRevive.props = result.props }
if (result.slots) { toRevive.slots = result.slots }
if (result.components) { toRevive.components = result.components }

nuxtApp.payload.data[key] = {
__nuxt_island: {
key,
...(import.meta.server && import.meta.prerender)
? {}
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } },
result: {
props: result.props,
slots: result.slots,
components: result.components
}
result: toRevive
},
...result
}
}

const payloads: Required<Pick<NuxtIslandResponse, 'slots' | 'components'>> = {
slots: {},
components: {}
}
const payloads: Partial<Pick<NuxtIslandResponse, 'slots' | 'components'>> = {}

if (instance.vnode.el) {
payloads.slots = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.slots ?? {}
payloads.components = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.components ?? {}
const slots = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.slots
if (slots) { payloads.slots = slots }
if (selectiveClient) {
const components = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.components
if (components) { payloads.components = components }
}
}

const ssrHTML = ref<string>('')
Expand All @@ -137,12 +139,15 @@ export default defineComponent({
}
}

return html.replaceAll(SLOT_FALLBACK_RE, (full, slotName) => {
if (!currentSlots.includes(slotName)) {
return full + (payloads.slots[slotName]?.fallback || '')
}
return full
})
if (payloads.slots) {
return html.replaceAll(SLOT_FALLBACK_RE, (full, slotName) => {
if (!currentSlots.includes(slotName)) {
return full + (payloads.slots?.[slotName]?.fallback || '')
}
return full
})
}
return html
})

const cHead = ref<Record<'link' | 'style', Array<Record<string, string>>>>({ link: [], style: [] })
Expand Down Expand Up @@ -256,24 +261,26 @@ export default defineComponent({
teleports.push(createVNode(Teleport,
// use different selectors for even and odd teleportKey to force trigger the teleport
{ to: import.meta.client ? `${isKeyOdd ? 'div' : ''}[data-island-uid="${uid.value}"][data-island-slot="${slot}"]` : `uid=${uid.value};slot=${slot}` },
{ default: () => (payloads.slots[slot].props?.length ? payloads.slots[slot].props : [{}]).map((data: any) => slots[slot]?.(data)) })
{ default: () => (payloads.slots?.[slot].props?.length ? payloads.slots[slot].props : [{}]).map((data: any) => slots[slot]?.(data)) })
)
}
}
if (selectiveClient) {
if (import.meta.server) {
for (const [id, info] of Object.entries(payloads.components ?? {})) {
const { html, slots } = info
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
for (const slot in slots) {
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
if (payloads.components) {
for (const [id, info] of Object.entries(payloads.components)) {
const { html, slots } = info
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
for (const slot in slots) {
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
}
teleports.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
default: () => [createStaticVNode(replaced, 1)]
}))
}
teleports.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}` }, {
default: () => [createStaticVNode(replaced, 1)]
}))
}
} else if (canLoadClientComponent.value) {
for (const [id, info] of Object.entries(payloads.components ?? {})) {
} else if (canLoadClientComponent.value && payloads.components) {
for (const [id, info] of Object.entries(payloads.components)) {
const { props, slots } = info
const component = components!.get(id)!
// use different selectors for even and odd teleportKey to force trigger the teleport
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/core/runtime/nitro/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/
const SSR_CLIENT_SLOT_MARKER = /^island-slot=(?:[^;]*);(.*)$/

function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['slots'] {
if (!ssrContext.islandContext) { return {} }
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.slots).length) { return undefined }
const response: NuxtIslandResponse['slots'] = {}
for (const slot in ssrContext.islandContext.slots) {
response[slot] = {
Expand All @@ -661,7 +661,7 @@ function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse[
}

function getClientIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['components'] {
if (!ssrContext.islandContext) { return {} }
if (!ssrContext.islandContext || !Object.keys(ssrContext.islandContext.components).length) { return undefined }
const response: NuxtIslandResponse['components'] = {}

for (const clientUid in ssrContext.islandContext.components) {
Expand Down
3 changes: 0 additions & 3 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1968,14 +1968,12 @@ describe('component islands', () => {

expect(result).toMatchInlineSnapshot(`
{
"components": {},
"head": {
"link": [],
"style": [],
},
"html": "<pre data-island-uid> Route: /foo
</pre>",
"slots": {},
"state": {},
}
`)
Expand All @@ -1993,7 +1991,6 @@ describe('component islands', () => {
result.html = result.html.replaceAll(/ (data-island-uid|data-island-component)="([^"]*)"/g, '')
expect(result).toMatchInlineSnapshot(`
{
"components": {},
"head": {
"link": [],
"style": [],
Expand Down

0 comments on commit 6dcad76

Please sign in to comment.