mirror of
https://github.com/nuxt/nuxt.git
synced 2025-03-19 07:51:18 +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: props.props ? JSON.stringify(props.props) : undefined,
|
||||
}))
|
||||
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
||||
// TODO: support passing on more headers
|
||||
if (import.meta.server && import.meta.prerender) {
|
||||
const hints = r.headers.get('x-nitro-prerender')
|
||||
if (hints) {
|
||||
appendResponseHeader(event!, 'x-nitro-prerender', hints)
|
||||
try {
|
||||
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
||||
// TODO: support passing on more headers
|
||||
if (import.meta.server && import.meta.prerender) {
|
||||
const hints = r.headers.get('x-nitro-prerender')
|
||||
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) {
|
||||
|
@ -2,6 +2,8 @@ import { defineComponent, getCurrentInstance, h, ref } from 'vue'
|
||||
import NuxtIsland from '#app/components/nuxt-island'
|
||||
import { useRoute } from '#app/composables/router'
|
||||
import { isPrerendered } from '#app/composables/payload'
|
||||
import { createError, showError } from '#app/composables/error'
|
||||
import { useNuxtApp } from '#app/nuxt'
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export const createServerComponent = (name: string) => {
|
||||
@ -46,10 +48,9 @@ export const createIslandPage = (name: string) => {
|
||||
expose({
|
||||
refresh: () => islandRef.value?.refresh(),
|
||||
})
|
||||
|
||||
const nuxtApp = useNuxtApp()
|
||||
const route = useRoute()
|
||||
const path = import.meta.client && await isPrerendered(route.path) ? route.path : route.fullPath.replace(/#.*$/, '')
|
||||
|
||||
return () => {
|
||||
return h('div', [
|
||||
h(NuxtIsland, {
|
||||
@ -57,6 +58,16 @@ export const createIslandPage = (name: string) => {
|
||||
lazy: props.lazy,
|
||||
ref: islandRef,
|
||||
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),
|
||||
])
|
||||
}
|
||||
|
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