mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-23 17:10:07 +00:00
feat(nuxt): working only with navigation (missing payload on app initialization)
This commit is contained in:
parent
2331d38e24
commit
202fe052f0
@ -1,6 +1,6 @@
|
|||||||
|
import { relative } from 'node:path'
|
||||||
import { Teleport, defineComponent, h } from 'vue'
|
import { Teleport, defineComponent, h } from 'vue'
|
||||||
import { useNuxtApp } from '#app'
|
import { useNuxtApp } from '#app'
|
||||||
import { relative } from 'path'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* component only used with componentsIsland
|
* component only used with componentsIsland
|
||||||
@ -24,7 +24,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup (props, { slots }) {
|
setup (props, { slots }) {
|
||||||
|
|
||||||
const app = useNuxtApp()
|
const app = useNuxtApp()
|
||||||
|
|
||||||
const islandContext = app.ssrContext!.islandContext
|
const islandContext = app.ssrContext!.islandContext
|
||||||
@ -33,14 +32,13 @@ export default defineComponent({
|
|||||||
console.log(slot)
|
console.log(slot)
|
||||||
if (process.dev) {
|
if (process.dev) {
|
||||||
console.log(app)
|
console.log(app)
|
||||||
const path = '__nuxt/' + relative(props.rootDir, slot.type.__file)
|
const path = '_nuxt/' + relative(props.rootDir, slot.type.__file)
|
||||||
|
|
||||||
islandContext.chunks[slot.type.__name] = path
|
islandContext.chunks[slot.type.__name] = path
|
||||||
}
|
}
|
||||||
islandContext.propsData[props.to] = slot.props || {}
|
islandContext.propsData[props.to] = slot.props || {}
|
||||||
// todo set prop in payload
|
// todo set prop in payload
|
||||||
return () => {
|
return () => {
|
||||||
|
|
||||||
if (props.nuxtClient) {
|
if (props.nuxtClient) {
|
||||||
return [h('div', {
|
return [h('div', {
|
||||||
style: 'display: contents;',
|
style: 'display: contents;',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { Component } from 'vue'
|
||||||
import { Fragment, Teleport, computed, createStaticVNode, createVNode, defineComponent, getCurrentInstance, h, nextTick, onMounted, ref, watch } from 'vue'
|
import { Fragment, Teleport, computed, createStaticVNode, createVNode, defineComponent, getCurrentInstance, h, nextTick, onMounted, ref, watch } from 'vue'
|
||||||
import { debounce } from 'perfect-debounce'
|
import { debounce } from 'perfect-debounce'
|
||||||
import { hash } from 'ohash'
|
import { hash } from 'ohash'
|
||||||
@ -6,6 +7,7 @@ import { useHead } from '@unhead/vue'
|
|||||||
import { randomUUID } from 'uncrypto'
|
import { randomUUID } from 'uncrypto'
|
||||||
import { joinURL, withQuery } from 'ufo'
|
import { joinURL, withQuery } from 'ufo'
|
||||||
import type { FetchResponse } from 'ofetch'
|
import type { FetchResponse } from 'ofetch'
|
||||||
|
import { join } from 'pathe'
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-restricted-paths
|
// eslint-disable-next-line import/no-restricted-paths
|
||||||
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
|
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
|
||||||
@ -24,18 +26,17 @@ const SLOTNAME_RE = /nuxt-ssr-slot-name="([^"]*)"/g
|
|||||||
const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g
|
const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g
|
||||||
|
|
||||||
let id = 0
|
let id = 0
|
||||||
const getId = process.client ? () => (id++).toString() : randomUUID
|
const getId = import.meta.client ? () => (id++).toString() : randomUUID
|
||||||
const components = process.client ? new Map<string, unknown>() : undefined
|
const components = import.meta.client ? new Map<string, Component>() : undefined
|
||||||
|
|
||||||
async function loadComponents (paths: Record<string, string>) {
|
async function loadComponents (source = '/', paths: Record<string, string>) {
|
||||||
const promises = []
|
const promises = []
|
||||||
|
|
||||||
debugger
|
|
||||||
for (const component in paths) {
|
for (const component in paths) {
|
||||||
if (!(components!.has(component))) {
|
if (!(components!.has(component))) {
|
||||||
promises.push((async () => {
|
promises.push((async () => {
|
||||||
const c = await import('http://localhost:3000/__nuxt/components/SugarCounter.vue')
|
const chunkSource = join(source, paths[component])
|
||||||
debugger
|
const c = await import(chunkSource)
|
||||||
components!.set(component, c.default ?? c)
|
components!.set(component, c.default ?? c)
|
||||||
})())
|
})())
|
||||||
}
|
}
|
||||||
@ -109,9 +110,24 @@ export default defineComponent({
|
|||||||
const uid = ref<string>(ssrHTML.value.match(SSR_UID_RE)?.[1] ?? randomUUID())
|
const uid = ref<string>(ssrHTML.value.match(SSR_UID_RE)?.[1] ?? randomUUID())
|
||||||
const availableSlots = computed(() => [...ssrHTML.value.matchAll(SLOTNAME_RE)].map(m => m[1]))
|
const availableSlots = computed(() => [...ssrHTML.value.matchAll(SLOTNAME_RE)].map(m => m[1]))
|
||||||
|
|
||||||
|
// no need for reactivity
|
||||||
|
let interactiveComponentsList: Record<string, Record<string, any>> = {}
|
||||||
|
|
||||||
const html = computed(() => {
|
const html = computed(() => {
|
||||||
const currentSlots = Object.keys(slots)
|
const currentSlots = Object.keys(slots)
|
||||||
return ssrHTML.value.replace(SLOT_FALLBACK_RE, (full, slotName, content) => {
|
let html = ssrHTML.value
|
||||||
|
if (process.client) {
|
||||||
|
const el = document.createElement('html')
|
||||||
|
el.innerHTML = html
|
||||||
|
Object.entries(interactiveComponentsList).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
|
// remove fallback to insert slots
|
||||||
if (currentSlots.includes(slotName)) {
|
if (currentSlots.includes(slotName)) {
|
||||||
return ''
|
return ''
|
||||||
@ -120,8 +136,6 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// no need for reactivity
|
|
||||||
let interactiveComponentsList = {}
|
|
||||||
function setUid () {
|
function setUid () {
|
||||||
uid.value = ssrHTML.value.match(SSR_UID_RE)?.[1] ?? getId() as string
|
uid.value = ssrHTML.value.match(SSR_UID_RE)?.[1] ?? getId() as string
|
||||||
}
|
}
|
||||||
@ -176,16 +190,16 @@ export default defineComponent({
|
|||||||
// must await next tick for Teleport to work correctly with static node re-rendering
|
// must await next tick for Teleport to work correctly with static node re-rendering
|
||||||
await nextTick()
|
await nextTick()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.client) {
|
||||||
|
await loadComponents(props.source, res.chunks)
|
||||||
|
interactiveComponentsList = res.props
|
||||||
|
}
|
||||||
|
|
||||||
setUid()
|
setUid()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = e
|
error.value = e
|
||||||
}
|
}
|
||||||
setUid()
|
|
||||||
|
|
||||||
if (process.client) {
|
|
||||||
await loadComponents(res.chunks)
|
|
||||||
interactiveComponentsList = res.props
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
@ -221,10 +235,11 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (process.client && html.value.includes('nuxt-ssr-client') && mounted.value) {
|
if (process.client && html.value.includes('nuxt-ssr-client') && mounted.value) {
|
||||||
|
for (const [id, props] of Object.entries(interactiveComponentsList)) {
|
||||||
for (const id in interactiveComponentsList) {
|
|
||||||
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: () => [h(components!.get(id.split('-')[0]), interactiveComponentsList[id])]
|
default: () => {
|
||||||
|
return [h(components!.get(id.split('-')[0])!, props)]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
nodes.push(vnode)
|
nodes.push(vnode)
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
islandHead.style.push({ key: 'island-style-' + hash(tag.innerHTML), innerHTML: tag.innerHTML })
|
islandHead.style.push({ key: 'island-style-' + hash(tag.innerHTML), innerHTML: tag.innerHTML })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const islandResponse: NuxtIslandResponse = {
|
const islandResponse: NuxtIslandResponse = {
|
||||||
id: islandContext.id,
|
id: islandContext.id,
|
||||||
head: islandHead,
|
head: islandHead,
|
||||||
|
Loading…
Reference in New Issue
Block a user