mirror of
https://github.com/PanJiaChen/vue-element-admin.git
synced 2026-06-14 00:59:13 +08:00
Merge 9444f9db28198900db0d03544200b2e683593c6c into 6858a9ad67483025f6a9432a926beb9327037be3
This commit is contained in:
commit
50cc6064f6
66
src/router/chunk-load-error.js
Normal file
66
src/router/chunk-load-error.js
Normal file
@ -0,0 +1,66 @@
|
||||
const chunkLoadErrorReloadKey = 'vue-element-admin:chunk-load-error-reload'
|
||||
const chunkLoadErrorRetryWindow = 10 * 1000
|
||||
|
||||
export function isChunkLoadError(error) {
|
||||
if (!error) {
|
||||
return false
|
||||
}
|
||||
|
||||
const name = error.name || ''
|
||||
const message = error.message || String(error)
|
||||
|
||||
return name === 'ChunkLoadError' ||
|
||||
/Loading (CSS )?chunk [\w-]+ failed/i.test(message) ||
|
||||
/ChunkLoadError/i.test(message)
|
||||
}
|
||||
|
||||
export function shouldReloadForChunkLoadError({
|
||||
href = window.location.href,
|
||||
storage = window.sessionStorage,
|
||||
now = Date.now()
|
||||
} = {}) {
|
||||
if (!storage) {
|
||||
return true
|
||||
}
|
||||
|
||||
let previousReload
|
||||
|
||||
try {
|
||||
previousReload = JSON.parse(storage.getItem(chunkLoadErrorReloadKey) || 'null')
|
||||
} catch (error) {
|
||||
previousReload = null
|
||||
}
|
||||
|
||||
if (
|
||||
previousReload &&
|
||||
previousReload.href === href &&
|
||||
now - previousReload.time < chunkLoadErrorRetryWindow
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
storage.setItem(chunkLoadErrorReloadKey, JSON.stringify({ href, time: now }))
|
||||
} catch (error) {
|
||||
// Ignore storage failures; a single reload is still the best recovery path.
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export function handleChunkLoadError(error, {
|
||||
href = window.location.href,
|
||||
storage = window.sessionStorage,
|
||||
reload = window.location.replace.bind(window.location),
|
||||
now = Date.now()
|
||||
} = {}) {
|
||||
if (!isChunkLoadError(error)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (shouldReloadForChunkLoadError({ href, storage, now })) {
|
||||
reload(href)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import { handleChunkLoadError } from './chunk-load-error'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
@ -395,6 +396,10 @@ const createRouter = () => new Router({
|
||||
|
||||
const router = createRouter()
|
||||
|
||||
router.onError(error => {
|
||||
handleChunkLoadError(error)
|
||||
})
|
||||
|
||||
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
|
||||
export function resetRouter() {
|
||||
const newRouter = createRouter()
|
||||
|
||||
48
tests/unit/router/chunk-load-error.spec.js
Normal file
48
tests/unit/router/chunk-load-error.spec.js
Normal file
@ -0,0 +1,48 @@
|
||||
import {
|
||||
handleChunkLoadError,
|
||||
isChunkLoadError,
|
||||
shouldReloadForChunkLoadError
|
||||
} from '@/router/chunk-load-error'
|
||||
|
||||
describe('router chunk-load error handling', () => {
|
||||
test('detects Webpack chunk load failures', () => {
|
||||
expect(isChunkLoadError(new Error('Loading chunk 12 failed.'))).toBe(true)
|
||||
expect(isChunkLoadError(new Error('Loading CSS chunk app failed.'))).toBe(true)
|
||||
expect(isChunkLoadError({ name: 'ChunkLoadError', message: 'missing' })).toBe(true)
|
||||
expect(isChunkLoadError(new Error('NavigationDuplicated'))).toBe(false)
|
||||
})
|
||||
|
||||
test('allows one reload for the same url in the retry window', () => {
|
||||
const storage = window.sessionStorage
|
||||
const href = 'http://localhost/#/dashboard'
|
||||
|
||||
storage.clear()
|
||||
|
||||
expect(shouldReloadForChunkLoadError({ href, storage, now: 1000 })).toBe(true)
|
||||
expect(shouldReloadForChunkLoadError({ href, storage, now: 2000 })).toBe(false)
|
||||
expect(shouldReloadForChunkLoadError({ href, storage, now: 12000 })).toBe(true)
|
||||
})
|
||||
|
||||
test('reloads the current page for a chunk load failure', () => {
|
||||
const reload = jest.fn()
|
||||
const storage = window.sessionStorage
|
||||
const href = 'http://localhost/#/permission/page'
|
||||
|
||||
storage.clear()
|
||||
|
||||
expect(handleChunkLoadError(new Error('Loading chunk 1 failed.'), {
|
||||
href,
|
||||
storage,
|
||||
reload,
|
||||
now: 1000
|
||||
})).toBe(true)
|
||||
expect(reload).toHaveBeenCalledWith(href)
|
||||
})
|
||||
|
||||
test('ignores unrelated router errors', () => {
|
||||
const reload = jest.fn()
|
||||
|
||||
expect(handleChunkLoadError(new Error('NavigationDuplicated'), { reload })).toBe(false)
|
||||
expect(reload).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user