mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 13:45:18 +00:00
perf(nuxt): prepopulate island payloads from rendered html (#22049)
Co-authored-by: Julien Huang <julien.huang@outlook.fr>
This commit is contained in:
parent
08acfb749d
commit
dcef9d94cd
@ -48,7 +48,33 @@ export default defineComponent({
|
||||
const mounted = ref(false)
|
||||
onMounted(() => { mounted.value = true })
|
||||
|
||||
const ssrHTML = ref<string>(process.client ? getFragmentHTML(instance.vnode?.el ?? null).join('') ?? '<div></div>' : '<div></div>')
|
||||
function setPayload (key: string, result: NuxtIslandResponse) {
|
||||
nuxtApp.payload.data[key] = {
|
||||
__nuxt_island: {
|
||||
key,
|
||||
...(process.server && process.env.prerender)
|
||||
? {}
|
||||
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } }
|
||||
},
|
||||
...result
|
||||
}
|
||||
}
|
||||
|
||||
const ssrHTML = ref('<div></div>')
|
||||
if (process.client) {
|
||||
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
|
||||
if (renderedHTML && nuxtApp.isHydrating) {
|
||||
setPayload(`${props.name}_${hashId.value}`, {
|
||||
html: getFragmentHTML(instance.vnode?.el ?? null, true).join(''),
|
||||
state: {},
|
||||
head: {
|
||||
link: [],
|
||||
style: []
|
||||
}
|
||||
})
|
||||
}
|
||||
ssrHTML.value = renderedHTML ?? '<div></div>'
|
||||
}
|
||||
const slotProps = computed(() => getSlotProps(ssrHTML.value))
|
||||
const uid = ref<string>(ssrHTML.value.match(SSR_UID_RE)?.[1] ?? randomUUID())
|
||||
const availableSlots = computed(() => [...ssrHTML.value.matchAll(SLOTNAME_RE)].map(m => m[1]))
|
||||
@ -91,20 +117,7 @@ export default defineComponent({
|
||||
appendResponseHeader(event, 'x-nitro-prerender', hints)
|
||||
}
|
||||
}
|
||||
nuxtApp.payload.data[key] = {
|
||||
__nuxt_island: {
|
||||
key,
|
||||
...(process.server && process.env.prerender)
|
||||
? {}
|
||||
: {
|
||||
params: {
|
||||
...props.context,
|
||||
props: props.props ? JSON.stringify(props.props) : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
...result
|
||||
}
|
||||
setPayload(key, result)
|
||||
return result
|
||||
}
|
||||
const key = ref(0)
|
||||
|
@ -99,25 +99,42 @@ export function vforToArray (source: any): any[] {
|
||||
return []
|
||||
}
|
||||
|
||||
export function getFragmentHTML (element: RendererNode | null) {
|
||||
/**
|
||||
* Retrieve the HTML content from an element
|
||||
* Handles `<!--[-->` Fragment elements
|
||||
*
|
||||
* @param element the element to retrieve the HTML
|
||||
* @param withoutSlots purge all slots from the HTML string retrieved
|
||||
* @returns {string[]} An array of string which represent the content of each element. Use `.join('')` to retrieve a component vnode.el HTML
|
||||
*/
|
||||
export function getFragmentHTML (element: RendererNode | null, withoutSlots = false) {
|
||||
if (element) {
|
||||
if (element.nodeName === '#comment' && element.nodeValue === '[') {
|
||||
return getFragmentChildren(element)
|
||||
return getFragmentChildren(element, [], withoutSlots)
|
||||
}
|
||||
if (withoutSlots) {
|
||||
const clone = element.cloneNode(true)
|
||||
clone.querySelectorAll('[nuxt-ssr-slot-name]').forEach((n: Element) => { n.innerHTML = '' })
|
||||
return [clone.outerHTML]
|
||||
}
|
||||
return [element.outerHTML]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
function getFragmentChildren (element: RendererNode | null, blocks: string[] = []) {
|
||||
function getFragmentChildren (element: RendererNode | null, blocks: string[] = [], withoutSlots = false) {
|
||||
if (element && element.nodeName) {
|
||||
if (isEndFragment(element)) {
|
||||
return blocks
|
||||
} else if (!isStartFragment(element)) {
|
||||
blocks.push(element.outerHTML)
|
||||
const clone = element.cloneNode(true) as Element
|
||||
if (withoutSlots) {
|
||||
clone.querySelectorAll('[nuxt-ssr-slot-name]').forEach((n) => { n.innerHTML = '' })
|
||||
}
|
||||
blocks.push(clone.outerHTML)
|
||||
}
|
||||
|
||||
getFragmentChildren(element.nextSibling, blocks)
|
||||
getFragmentChildren(element.nextSibling, blocks, withoutSlots)
|
||||
}
|
||||
return blocks
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user