// 路由页面代码模块加载失败的自愈处理。
|
// Vite 重启/依赖预构建刷新、发布后旧分包失效时,页面首次 import 会失败,
|
// 稍后重试或整页刷新即可恢复,不需要用户手动按 F5。
|
const CHUNK_LOAD_ERROR = /Failed to fetch dynamically imported module|Importing a module script failed|Loading chunk .* failed|Outdated Optimize Dep/i
|
|
export function isChunkLoadError(error) {
|
if (!error) return false
|
return CHUNK_LOAD_ERROR.test(error.message || String(error))
|
}
|
|
export async function importWithRetry(loader, retries = 2, delay = 500) {
|
for (let attempt = 0; ; attempt++) {
|
try {
|
return await loader()
|
} catch (error) {
|
if (attempt >= retries || !isChunkLoadError(error)) throw error
|
await new Promise(resolve => setTimeout(resolve, delay * 2 ** attempt))
|
}
|
}
|
}
|
|
const RELOAD_STATE_KEY = 'lims-chunk-load-reload'
|
const RELOAD_WINDOW = 60 * 1000
|
const RELOAD_LIMIT = 3
|
|
// 重试后仍失败则自动整页刷新;60 秒内最多 3 次,避免真正故障时无限刷新。
|
export function autoReloadForChunkError() {
|
const now = Date.now()
|
let state = null
|
try {
|
state = JSON.parse(sessionStorage.getItem(RELOAD_STATE_KEY) || 'null')
|
} catch (e) {
|
state = null
|
}
|
if (!state || now - state.first > RELOAD_WINDOW) {
|
state = { first: now, count: 0 }
|
}
|
if (state.count >= RELOAD_LIMIT) return false
|
state.count += 1
|
try {
|
sessionStorage.setItem(RELOAD_STATE_KEY, JSON.stringify(state))
|
} catch (e) {
|
// 隐私模式等存储不可用时忽略,不影响刷新
|
}
|
setTimeout(() => window.location.reload(), 500)
|
return true
|
}
|