From ffc4e798cd39d57124f11cae688f5d4132d61739 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Sun, 30 Jul 2023 23:00:41 +0200 Subject: [PATCH] feat(nuxt): allow remote sources for islands (#21592) --- .../nuxt/src/app/components/nuxt-island.ts | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index c268265d6c..3f8bfd3876 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -36,12 +36,17 @@ export default defineComponent({ context: { type: Object, default: () => ({}) + }, + source: { + type: String, + default: () => undefined } }, async setup (props, { slots }) { + const error = ref(null) const config = useRuntimeConfig() const nuxtApp = useNuxtApp() - const hashId = computed(() => hash([props.name, props.props, props.context])) + const hashId = computed(() => hash([props.name, props.props, props.context, props.source])) const instance = getCurrentInstance()! const event = useRequestEvent() // TODO: remove use of `$fetch.raw` when nitro 503 issues on windows dev server are resolved @@ -100,7 +105,8 @@ export default defineComponent({ const key = `${props.name}_${hashId.value}` if (nuxtApp.payload.data[key] && !force) { return nuxtApp.payload.data[key] } - const url = `/__nuxt_island/${key}` + const url = props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}` + if (process.server && process.env.prerender) { // Hint to Nitro to prerender the island component appendResponseHeader(event, 'x-nitro-prerender', url) @@ -130,18 +136,23 @@ export default defineComponent({ delete nuxtApp[pKey]![uid.value] }) } - const res: NuxtIslandResponse = await nuxtApp[pKey][uid.value] - cHead.value.link = res.head.link - cHead.value.style = res.head.style - ssrHTML.value = res.html.replace(UID_ATTR, () => { - return `nuxt-ssr-component-uid="${getId()}"` - }) - key.value++ - if (process.client) { - // must await next tick for Teleport to work correctly with static node re-rendering - await nextTick() + try { + const res: NuxtIslandResponse = await nuxtApp[pKey][uid.value] + cHead.value.link = res.head.link + cHead.value.style = res.head.style + ssrHTML.value = res.html.replace(UID_ATTR, () => { + return `nuxt-ssr-component-uid="${getId()}"` + }) + key.value++ + error.value = null + if (process.client) { + // must await next tick for Teleport to work correctly with static node re-rendering + await nextTick() + } + setUid() + } catch (e) { + error.value = e } - setUid() } if (import.meta.hot) { @@ -160,6 +171,9 @@ export default defineComponent({ } return () => { + if (error.value && slots.fallback) { + return [slots.fallback({ error: error.value })] + } const nodes = [createVNode(Fragment, { key: key.value }, [h(createStaticVNode(html.value, 1))])]