refactor: move shared const to utils

This commit is contained in:
Julien Huang 2023-12-24 18:21:27 +01:00
parent 6f3406e640
commit 0c7afecded
3 changed files with 22 additions and 31 deletions

View File

@ -2,9 +2,7 @@ import type { Component } from 'vue'
import { Fragment, Teleport, computed, createStaticVNode, createVNode, defineComponent, getCurrentInstance, h, nextTick, onMounted, ref, toRaw, watch } from 'vue'
import { debounce } from 'perfect-debounce'
import { hash } from 'ohash'
import { appendResponseHeader } from 'h3'
import { useHead } from '@unhead/vue'
import { randomUUID } from 'uncrypto'
import { joinURL, withQuery } from 'ufo'
import type { FetchResponse } from 'ofetch'
import { join } from 'pathe'
@ -12,18 +10,11 @@ import { join } from 'pathe'
// eslint-disable-next-line import/no-restricted-paths
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { useRequestEvent } from '../composables/ssr'
import { getFragmentHTML, getSlotProps } from './utils'
import { SLOTNAME_RE, SLOT_FALLBACK_RE, SSR_UID_RE, UID_ATTR, getFragmentHTML, getSlotProps, pKey } from './utils'
// @ts-expect-error virtual file
import { remoteComponentIslands, selectiveClient } from '#build/nuxt.config.mjs'
const pKey = '_islandPromises'
const SSR_UID_RE = /nuxt-ssr-component-uid="([^"]*)"/
const UID_ATTR = /nuxt-ssr-component-uid(="([^"]*)")?/
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
let id = 0
const getId = () => (id++).toString()
@ -111,12 +102,6 @@ export default defineComponent({
// If not hydrating, fetchComponent() will set it
const rawPayload = nuxtApp.isHydrating ? toRaw(nuxtApp.payload.data)?.[`${props.name}_${hashId.value}`] ?? emptyPayload() : emptyPayload()
const nonReactivePayload: Pick<NuxtIslandResponse, 'chunks'| 'props' | 'teleports'> = {
chunks: rawPayload.chunks,
props: rawPayload.props,
teleports: rawPayload.teleports
}
const ssrHTML = ref<string>(getFragmentHTML(instance.vnode?.el ?? null, true)?.join('') || '')
const slotProps = computed(() => getSlotProps(ssrHTML.value))
@ -128,7 +113,7 @@ export default defineComponent({
let html = ssrHTML.value
if (!canLoadClientComponent.value) {
for (const [key, value] of Object.entries(nonReactivePayload.teleports || {})) {
for (const [key, value] of Object.entries(rawPayload.teleports || {})) {
html = html.replace(new RegExp(`<div [^>]*nuxt-ssr-client="${key}"[^>]*>`), (full) => {
return full + value
})
@ -191,10 +176,10 @@ export default defineComponent({
if (canLoadClientComponent.value && res.chunks) {
await loadComponents(props.source, res.chunks)
}
nonReactivePayload.props = res.props
rawPayload.props = res.props
}
nonReactivePayload.teleports = res.teleports
nonReactivePayload.chunks = res.chunks
rawPayload.teleports = res.teleports
rawPayload.chunks = res.chunks
// must await next tick for Teleport to work correctly with static node re-rendering
await nextTick()
@ -221,8 +206,8 @@ export default defineComponent({
fetchComponent()
} else if (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered) {
await fetchComponent()
} else if (selectiveClient && canLoadClientComponent.value && nonReactivePayload.chunks) {
await loadComponents(props.source, nonReactivePayload.chunks)
} else if (selectiveClient && canLoadClientComponent.value && rawPayload.chunks) {
await loadComponents(props.source, rawPayload.chunks)
}
return () => {
@ -234,6 +219,7 @@ export default defineComponent({
}, [h(createStaticVNode(html.value || '<div></div>', 1))])]
if (uid.value && (mounted.value || nuxtApp.isHydrating) && html.value) {
// render slots
for (const slot in slots) {
if (availableSlots.value.includes(slot)) {
nodes.push(createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` }, {
@ -241,8 +227,10 @@ export default defineComponent({
}))
}
}
// render components
if (selectiveClient && canLoadClientComponent.value) {
for (const [id, props] of Object.entries(nonReactivePayload.props ?? {})) {
for (const [id, props] of Object.entries(rawPayload.props ?? {})) {
const component = components!.get(id.split('-')[0])!
const vnode = createVNode(Teleport, { to: `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-client="${id}"]` }, {
default: () => {

View File

@ -9,16 +9,11 @@ import { joinURL, withQuery } from 'ufo'
import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer'
import { useNuxtApp, useRuntimeConfig } from '../nuxt'
import { prerenderRoutes, useRequestEvent } from '../composables/ssr'
import { getSlotProps } from './utils'
import { SLOTNAME_RE, SSR_UID_RE, UID_ATTR, getSlotProps, pKey } from './utils'
// @ts-expect-error virtual file
import { remoteComponentIslands, selectiveClient } from '#build/nuxt.config.mjs'
const pKey = '_islandPromises'
const SSR_UID_RE = /nuxt-ssr-component-uid="([^"]*)"/
const UID_ATTR = /nuxt-ssr-component-uid(="([^"]*)")?/
const SLOTNAME_RE = /nuxt-ssr-slot-name="([^"]*)"/g
export default defineComponent({
name: 'NuxtIsland',
props: {
@ -52,7 +47,6 @@ export default defineComponent({
const hashId = computed(() => hash([props.name, filteredProps.value, props.context, props.source]))
const event = useRequestEvent()
function setPayload(key: string, result: NuxtIslandResponse) {
nuxtApp.payload.data[key] = {
__nuxt_island: {
@ -117,7 +111,7 @@ export default defineComponent({
return result
}
async function fetchComponent(force = false) {
async function fetchComponent() {
nuxtApp[pKey] = nuxtApp[pKey] || {}
if (!nuxtApp[pKey][uid.value]) {
nuxtApp[pKey][uid.value] = _fetchComponent().finally(() => {

View File

@ -185,3 +185,12 @@ export function getSlotProps (html: string) {
}
return data
}
/**
* key used to share island promises
*/
export const pKey = '_islandPromises'
export const SSR_UID_RE = /nuxt-ssr-component-uid="([^"]*)"/
export const UID_ATTR = /nuxt-ssr-component-uid(="([^"]*)")?/
export const SLOTNAME_RE = /nuxt-ssr-slot-name="([^"]*)"/g
export const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g