mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 07:05:11 +00:00
fix(nuxt): catch chunk errors directly in navigation
This commit is contained in:
parent
a341e680fb
commit
be622645e0
@ -375,7 +375,9 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
if (chunkErrorEvent) {
|
if (chunkErrorEvent) {
|
||||||
window.addEventListener(chunkErrorEvent, (event) => {
|
window.addEventListener(chunkErrorEvent, (event) => {
|
||||||
nuxtApp.callHook('app:chunkError', { error: (event as Event & { payload: Error }).payload })
|
nuxtApp.callHook('app:chunkError', { error: (event as Event & { payload: Error }).payload })
|
||||||
|
if (nuxtApp.isHydrating || event.payload.message.includes('Unable to preload CSS')) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.useNuxtApp = window.useNuxtApp || useNuxtApp
|
window.useNuxtApp = window.useNuxtApp || useNuxtApp
|
||||||
|
@ -10,7 +10,7 @@ export default defineNuxtPlugin({
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
const chunkErrors = new Set()
|
const chunkErrors = new Set<Error>()
|
||||||
|
|
||||||
router.beforeEach(() => { chunkErrors.clear() })
|
router.beforeEach(() => { chunkErrors.clear() })
|
||||||
nuxtApp.hook('app:chunkError', ({ error }) => { chunkErrors.add(error) })
|
nuxtApp.hook('app:chunkError', ({ error }) => { chunkErrors.add(error) })
|
||||||
@ -26,7 +26,7 @@ export default defineNuxtPlugin({
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.onError((error, to) => {
|
router.onError((error, to) => {
|
||||||
if (chunkErrors.has(error) || error.message.includes('Failed to fetch dynamically imported module')) {
|
if (chunkErrors.has(error)) {
|
||||||
reloadAppAtPath(to)
|
reloadAppAtPath(to)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1165,16 +1165,29 @@ describe('errors', () => {
|
|||||||
|
|
||||||
// TODO: need to create test for webpack
|
// TODO: need to create test for webpack
|
||||||
it.runIf(!isDev())('should handle chunk loading errors', async () => {
|
it.runIf(!isDev())('should handle chunk loading errors', async () => {
|
||||||
const { page, consoleLogs } = await renderPage('/')
|
const { page, consoleLogs } = await renderPage()
|
||||||
|
await page.route(/\.css/, route => route.abort('timedout')) // verify CSS link preload failure doesn't break the page
|
||||||
|
await page.goto(url('/'))
|
||||||
|
await page.waitForFunction(() => window.useNuxtApp?.()._route.fullPath === '/' && !window.useNuxtApp?.().isHydrating)
|
||||||
|
|
||||||
|
const initialLogs = consoleLogs.map(c => c.text).join('')
|
||||||
|
expect(initialLogs).toContain('caught chunk load error')
|
||||||
|
consoleLogs.length = 0
|
||||||
|
|
||||||
await page.getByText('Increment state').click()
|
await page.getByText('Increment state').click()
|
||||||
await page.getByText('Increment state').click()
|
await page.getByText('Increment state').click()
|
||||||
expect(await page.innerText('div')).toContain('Some value: 3')
|
expect(await page.innerText('div')).toContain('Some value: 3')
|
||||||
await page.route(/.*/, route => route.abort('timedout'), { times: 1 })
|
await page.route(/.*/, route => route.abort('timedout'), { times: 1 })
|
||||||
await page.getByText('Chunk error').click()
|
await page.getByText('Chunk error').click()
|
||||||
|
|
||||||
await page.waitForURL(url('/chunk-error'))
|
await page.waitForURL(url('/chunk-error'))
|
||||||
expect(consoleLogs.map(c => c.text).join('')).toContain('Failed to load resource')
|
|
||||||
expect(await page.innerText('div')).toContain('Chunk error page')
|
const logs = consoleLogs.map(c => c.text).join('')
|
||||||
|
expect(logs).toContain('caught chunk load error')
|
||||||
|
expect(logs).toContain('Failed to load resource')
|
||||||
|
|
||||||
await page.waitForFunction(() => window.useNuxtApp?.()._route.fullPath === '/chunk-error')
|
await page.waitForFunction(() => window.useNuxtApp?.()._route.fullPath === '/chunk-error')
|
||||||
|
expect(await page.innerText('div')).toContain('Chunk error page')
|
||||||
await page.locator('div').getByText('State: 3').waitFor()
|
await page.locator('div').getByText('State: 3').waitFor()
|
||||||
|
|
||||||
await page.close()
|
await page.close()
|
||||||
|
5
test/fixtures/basic/plugins/chunk-error.ts
vendored
Normal file
5
test/fixtures/basic/plugins/chunk-error.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
nuxtApp.hook('app:chunkError', () => {
|
||||||
|
console.log('caught chunk load error')
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user