mirror of
https://github.com/nuxt/nuxt.git
synced 2025-03-21 08:45:53 +00:00
fix(nuxt): show error page on island page error (#31081)
This commit is contained in:
parent
6f8cfd679d
commit
d153ea9d23
@ -184,16 +184,23 @@ export default defineComponent({
|
|||||||
...props.context,
|
...props.context,
|
||||||
props: props.props ? JSON.stringify(props.props) : undefined,
|
props: props.props ? JSON.stringify(props.props) : undefined,
|
||||||
}))
|
}))
|
||||||
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
try {
|
||||||
// TODO: support passing on more headers
|
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
||||||
if (import.meta.server && import.meta.prerender) {
|
// TODO: support passing on more headers
|
||||||
const hints = r.headers.get('x-nitro-prerender')
|
if (import.meta.server && import.meta.prerender) {
|
||||||
if (hints) {
|
const hints = r.headers.get('x-nitro-prerender')
|
||||||
appendResponseHeader(event!, 'x-nitro-prerender', hints)
|
if (hints) {
|
||||||
|
appendResponseHeader(event!, 'x-nitro-prerender', hints)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setPayload(key, result)
|
||||||
|
return result
|
||||||
|
} catch (e: any) {
|
||||||
|
if (r.status !== 200) {
|
||||||
|
throw new Error(e.toString(), { cause: r })
|
||||||
|
}
|
||||||
|
throw e
|
||||||
}
|
}
|
||||||
setPayload(key, result)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchComponent (force = false) {
|
async function fetchComponent (force = false) {
|
||||||
|
@ -2,6 +2,8 @@ import { defineComponent, getCurrentInstance, h, ref } from 'vue'
|
|||||||
import NuxtIsland from '#app/components/nuxt-island'
|
import NuxtIsland from '#app/components/nuxt-island'
|
||||||
import { useRoute } from '#app/composables/router'
|
import { useRoute } from '#app/composables/router'
|
||||||
import { isPrerendered } from '#app/composables/payload'
|
import { isPrerendered } from '#app/composables/payload'
|
||||||
|
import { createError, showError } from '#app/composables/error'
|
||||||
|
import { useNuxtApp } from '#app/nuxt'
|
||||||
|
|
||||||
/* @__NO_SIDE_EFFECTS__ */
|
/* @__NO_SIDE_EFFECTS__ */
|
||||||
export const createServerComponent = (name: string) => {
|
export const createServerComponent = (name: string) => {
|
||||||
@ -46,10 +48,9 @@ export const createIslandPage = (name: string) => {
|
|||||||
expose({
|
expose({
|
||||||
refresh: () => islandRef.value?.refresh(),
|
refresh: () => islandRef.value?.refresh(),
|
||||||
})
|
})
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const path = import.meta.client && await isPrerendered(route.path) ? route.path : route.fullPath.replace(/#.*$/, '')
|
const path = import.meta.client && await isPrerendered(route.path) ? route.path : route.fullPath.replace(/#.*$/, '')
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return h('div', [
|
return h('div', [
|
||||||
h(NuxtIsland, {
|
h(NuxtIsland, {
|
||||||
@ -57,6 +58,16 @@ export const createIslandPage = (name: string) => {
|
|||||||
lazy: props.lazy,
|
lazy: props.lazy,
|
||||||
ref: islandRef,
|
ref: islandRef,
|
||||||
context: { url: path },
|
context: { url: path },
|
||||||
|
onError: (e) => {
|
||||||
|
if (e.cause && e.cause instanceof Response) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: e.cause.status,
|
||||||
|
statusText: e.cause.statusText,
|
||||||
|
status: e.cause.status,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
nuxtApp.runWithContext(() => showError(e))
|
||||||
|
},
|
||||||
}, slots),
|
}, slots),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
26
test/nuxt/island-pages.test.ts
Normal file
26
test/nuxt/island-pages.test.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
||||||
|
import { flushPromises } from '@vue/test-utils'
|
||||||
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
import { Suspense } from 'vue'
|
||||||
|
import { createIslandPage } from '~/packages/nuxt/src/components/runtime/server-component'
|
||||||
|
|
||||||
|
vi.mock('#app/composables/error', async (og) => {
|
||||||
|
return {
|
||||||
|
...(await og()),
|
||||||
|
showError: vi.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Island pages', () => {
|
||||||
|
it('expect to show error', async () => {
|
||||||
|
await mountSuspended({
|
||||||
|
setup () {
|
||||||
|
return () => h(Suspense, {}, {
|
||||||
|
default: () => h(createIslandPage('pagedontexist')),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await flushPromises()
|
||||||
|
expect(showError).toHaveBeenCalledOnce()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user