From 0c7afecded2e21304e58062b0215ea84ad5fd823 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sun, 24 Dec 2023 18:21:27 +0100 Subject: [PATCH] refactor: move shared const to utils --- .../src/app/components/nuxt-island.client.ts | 34 ++++++------------- .../src/app/components/nuxt-island.server.ts | 10 ++---- packages/nuxt/src/app/components/utils.ts | 9 +++++ 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/packages/nuxt/src/app/components/nuxt-island.client.ts b/packages/nuxt/src/app/components/nuxt-island.client.ts index c1e2441813..48f7fd5148 100644 --- a/packages/nuxt/src/app/components/nuxt-island.client.ts +++ b/packages/nuxt/src/app/components/nuxt-island.client.ts @@ -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>(((?!
]*>)[\s\S])*)
]*><\/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 = { - chunks: rawPayload.chunks, - props: rawPayload.props, - teleports: rawPayload.teleports - } - const ssrHTML = ref(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(`
]*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 || '
', 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: () => { diff --git a/packages/nuxt/src/app/components/nuxt-island.server.ts b/packages/nuxt/src/app/components/nuxt-island.server.ts index e83ef38d99..3dbaa37446 100644 --- a/packages/nuxt/src/app/components/nuxt-island.server.ts +++ b/packages/nuxt/src/app/components/nuxt-island.server.ts @@ -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(() => { diff --git a/packages/nuxt/src/app/components/utils.ts b/packages/nuxt/src/app/components/utils.ts index dbe8d23744..3d49e96e86 100644 --- a/packages/nuxt/src/app/components/utils.ts +++ b/packages/nuxt/src/app/components/utils.ts @@ -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>(((?!
]*>)[\s\S])*)
]*><\/div>/g