mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-13 09:33:54 +00:00
perf(nuxt): reduce nuxt island payload (#26569)
This commit is contained in:
parent
41ab12414f
commit
6dcad76a06
@ -88,30 +88,32 @@ export default defineComponent({
|
|||||||
onMounted(() => { mounted.value = true; teleportKey.value++ })
|
onMounted(() => { mounted.value = true; teleportKey.value++ })
|
||||||
|
|
||||||
function setPayload (key: string, result: NuxtIslandResponse) {
|
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] = {
|
nuxtApp.payload.data[key] = {
|
||||||
__nuxt_island: {
|
__nuxt_island: {
|
||||||
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: {
|
result: toRevive
|
||||||
props: result.props,
|
|
||||||
slots: result.slots,
|
|
||||||
components: result.components
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
...result
|
...result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const payloads: Required<Pick<NuxtIslandResponse, 'slots' | 'components'>> = {
|
const payloads: Partial<Pick<NuxtIslandResponse, 'slots' | 'components'>> = {}
|
||||||
slots: {},
|
|
||||||
components: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance.vnode.el) {
|
if (instance.vnode.el) {
|
||||||
payloads.slots = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.slots ?? {}
|
const slots = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.slots
|
||||||
payloads.components = toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}`])?.components ?? {}
|
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>('')
|
const ssrHTML = ref<string>('')
|
||||||
@ -137,12 +139,15 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return html.replaceAll(SLOT_FALLBACK_RE, (full, slotName) => {
|
if (payloads.slots) {
|
||||||
if (!currentSlots.includes(slotName)) {
|
return html.replaceAll(SLOT_FALLBACK_RE, (full, slotName) => {
|
||||||
return full + (payloads.slots[slotName]?.fallback || '')
|
if (!currentSlots.includes(slotName)) {
|
||||||
}
|
return full + (payloads.slots?.[slotName]?.fallback || '')
|
||||||
return full
|
}
|
||||||
})
|
return full
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return html
|
||||||
})
|
})
|
||||||
|
|
||||||
const cHead = ref<Record<'link' | 'style', Array<Record<string, string>>>>({ link: [], style: [] })
|
const cHead = ref<Record<'link' | 'style', Array<Record<string, string>>>>({ link: [], style: [] })
|
||||||
@ -256,24 +261,26 @@ export default defineComponent({
|
|||||||
teleports.push(createVNode(Teleport,
|
teleports.push(createVNode(Teleport,
|
||||||
// use different selectors for even and odd teleportKey to force trigger the 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}` },
|
{ 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 (selectiveClient) {
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
for (const [id, info] of Object.entries(payloads.components ?? {})) {
|
if (payloads.components) {
|
||||||
const { html, slots } = info
|
for (const [id, info] of Object.entries(payloads.components)) {
|
||||||
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
|
const { html, slots } = info
|
||||||
for (const slot in slots) {
|
let replaced = html.replaceAll('data-island-uid', `data-island-uid="${uid.value}"`)
|
||||||
replaced = replaced.replaceAll(`data-island-slot="${slot}">`, full => full + slots[slot])
|
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) {
|
} else if (canLoadClientComponent.value && payloads.components) {
|
||||||
for (const [id, info] of Object.entries(payloads.components ?? {})) {
|
for (const [id, info] of Object.entries(payloads.components)) {
|
||||||
const { props, slots } = info
|
const { props, slots } = info
|
||||||
const component = components!.get(id)!
|
const component = components!.get(id)!
|
||||||
// use different selectors for even and odd teleportKey to force trigger the teleport
|
// use different selectors for even and odd teleportKey to force trigger the teleport
|
||||||
|
@ -649,7 +649,7 @@ const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/
|
|||||||
const SSR_CLIENT_SLOT_MARKER = /^island-slot=(?:[^;]*);(.*)$/
|
const SSR_CLIENT_SLOT_MARKER = /^island-slot=(?:[^;]*);(.*)$/
|
||||||
|
|
||||||
function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['slots'] {
|
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'] = {}
|
const response: NuxtIslandResponse['slots'] = {}
|
||||||
for (const slot in ssrContext.islandContext.slots) {
|
for (const slot in ssrContext.islandContext.slots) {
|
||||||
response[slot] = {
|
response[slot] = {
|
||||||
@ -661,7 +661,7 @@ function getSlotIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse[
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getClientIslandResponse (ssrContext: NuxtSSRContext): NuxtIslandResponse['components'] {
|
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'] = {}
|
const response: NuxtIslandResponse['components'] = {}
|
||||||
|
|
||||||
for (const clientUid in ssrContext.islandContext.components) {
|
for (const clientUid in ssrContext.islandContext.components) {
|
||||||
|
@ -1968,14 +1968,12 @@ describe('component islands', () => {
|
|||||||
|
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"components": {},
|
|
||||||
"head": {
|
"head": {
|
||||||
"link": [],
|
"link": [],
|
||||||
"style": [],
|
"style": [],
|
||||||
},
|
},
|
||||||
"html": "<pre data-island-uid> Route: /foo
|
"html": "<pre data-island-uid> Route: /foo
|
||||||
</pre>",
|
</pre>",
|
||||||
"slots": {},
|
|
||||||
"state": {},
|
"state": {},
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
@ -1993,7 +1991,6 @@ describe('component islands', () => {
|
|||||||
result.html = result.html.replaceAll(/ (data-island-uid|data-island-component)="([^"]*)"/g, '')
|
result.html = result.html.replaceAll(/ (data-island-uid|data-island-component)="([^"]*)"/g, '')
|
||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"components": {},
|
|
||||||
"head": {
|
"head": {
|
||||||
"link": [],
|
"link": [],
|
||||||
"style": [],
|
"style": [],
|
||||||
|
Loading…
Reference in New Issue
Block a user