feat: WORTKING IN BUIKLD

This commit is contained in:
julien huang 2023-08-14 16:54:51 +02:00
parent 38ba957027
commit cbd94c373e
3 changed files with 47 additions and 21 deletions

View File

@ -49,7 +49,7 @@ export default defineComponent({
return [h('div', {
style: 'display: contents;',
'nuxt-ssr-client': props.to
}, [slot]), h(Teleport, { to: props.to }, slot)]
}, []), h(Teleport, { to: props.to }, slot)]
}
return slot

View File

@ -113,23 +113,11 @@ export default defineComponent({
// no need for reactivity
let interactiveProps: Record<string, Record<string, any>> = process.client && nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data[`${props.name}_${hashId.value}_interactive`].props) : {}
const interactiveChunksList = process.client && nuxtApp.isHydrating ? nuxtApp.payload.data[`${props.name}_${hashId.value}_interactive`].chunks : {}
let interactiveTeleports = {}
const html = computed(() => {
const currentSlots = Object.keys(slots)
let html = ssrHTML.value
if (import.meta.client && mounted.value) {
const el = document.createElement('div')
el.innerHTML = html
Object.entries(interactiveProps).forEach(([id]) => {
const interactiveWrapper = el.querySelector(`[nuxt-ssr-client="${id}"]`)
if (interactiveWrapper) {
interactiveWrapper.innerHTML = ''
}
})
html = el.innerHTML
}
return html.replace(SLOT_FALLBACK_RE, (full, slotName, content) => {
// remove fallback to insert slots
if (currentSlots.includes(slotName)) {
@ -201,6 +189,8 @@ export default defineComponent({
if (process.client) {
await loadComponents(props.source, res.chunks)
interactiveProps = res.props
} else {
interactiveTeleports = res.teleports ||{}
}
setUid()
@ -244,7 +234,21 @@ export default defineComponent({
}))
}
}
if (process.client && html.value.includes('nuxt-ssr-client') && mounted.value) {
if (process.server) {
for (const [id, html] of Object.entries(interactiveTeleports)) {
console.log(id, html)
nuxtApp.ssrContext.teleports = nuxtApp.ssrContext.teleports || {}
nuxtApp.ssrContext.teleports[`uid=${uid.value};client=${id}`] = html
console.log("TPPPPPPPPP CA MARCHE PASSSSSSSSSSSSSSSSSSSSSSSSS", nuxtApp.ssrContext.teleports || {}
)
// nodes.push(createVNode(Teleport, { to: `uid=${uid.value};client=${id}`}, {
// default: () => {
// return createStaticVNode(html, 1)
// }
// }))
}
}
if (process.client && html.value.includes('nuxt-ssr-client') ) {
for (const [id, props] of Object.entries(interactiveProps)) {
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}"]` }, {

View File

@ -71,6 +71,7 @@ export interface NuxtIslandResponse {
}
chunks: Record<string, string>
props: Record<string, Record<string, any>>
teleports: Record<string, string>
}
export interface NuxtRenderResponse {
@ -192,7 +193,8 @@ async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
props: destr(context.props) || {},
uid: destr(context.uid) || undefined,
chunks: {},
propsData: {}
propsData: {},
teleports: {}
}
return ctx
@ -403,7 +405,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
head: normalizeChunks([headTags, ssrContext.styles]),
bodyAttrs: [bodyAttrs],
bodyPrepend: normalizeChunks([bodyTagsOpen, ssrContext.teleports?.body]),
body: [process.env.NUXT_COMPONENT_ISLANDS ? replaceServerOnlyComponentsSlots(ssrContext, _rendered.html) : _rendered.html],
body: [process.env.NUXT_COMPONENT_ISLANDS ? replaceClientTeleport(ssrContext, replaceServerOnlyComponentsSlots(ssrContext, _rendered.html)) : _rendered.html],
bodyAppend: [bodyTags]
}
@ -424,14 +426,14 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
islandHead.style.push({ key: 'island-style-' + hash(tag.innerHTML), innerHTML: tag.innerHTML })
}
}
const islandResponse: NuxtIslandResponse = {
id: islandContext.id,
head: islandHead,
html: getServerComponentHTML(htmlContext.body),
state: ssrContext.payload.state,
chunks: islandContext.chunks,
props: islandContext.propsData
props: islandContext.propsData,
teleports: ssrContext.teleports
}
await nitroApp.hooks.callHook('render:island', islandResponse, { event, islandContext })
@ -577,6 +579,7 @@ function getServerComponentHTML (body: string[]): string {
}
const SSR_TELEPORT_MARKER = /^uid=([^;]*);slot=(.*)$/
const SSR_CLIENT_TELEPORT_MARKER = /^uid=([^;]*);client=(.*)$/
function replaceServerOnlyComponentsSlots (ssrContext: NuxtSSRContext, html: string): string {
const { teleports, islandContext } = ssrContext
if (islandContext || !teleports) { return html }
@ -591,3 +594,22 @@ function replaceServerOnlyComponentsSlots (ssrContext: NuxtSSRContext, html: str
}
return html
}
function replaceClientTeleport (ssrContext: NuxtSSRContext, html: string) {
const { teleports, islandContext } = ssrContext
if (islandContext || !teleports) { return html }
for (const key in teleports) {
const match = key.match(SSR_CLIENT_TELEPORT_MARKER)
console.log(ssrContext.teleports)
if (!match) { continue }
const [, uid, clientId] = match
if (!uid || !clientId) { continue }
html = html.replace(new RegExp(`<div nuxt-ssr-component-uid="${uid}"[^>]*>((?!nuxt-ssr-client="${clientId}"|nuxt-ssr-component-uid)[\\s\\S])*<div [^>]*nuxt-ssr-client="${clientId}"[^>]*>`), (full) => {
return full + teleports[key]
})
console.log(html, 'HTMLLLLLLLL')
}
return html
}