fix: 懒加载chunk失败时自动刷新页面
部署后旧chunk文件名(带hash)被删除,浏览器若缓存了旧index.html 仍会请求旧chunk导致 "Failed to fetch dynamically imported module"。 新增 lazyRetry 包装器,检测到此错误时自动刷新页面获取新index.html。 用 sessionStorage 标记防止无限刷新。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { lazy, ComponentType } from 'react'
|
||||
|
||||
/**
|
||||
* 带自动重试的懒加载。
|
||||
*
|
||||
* 部署后旧 chunk 文件名(带 hash)被删除,浏览器若缓存了旧 index.html
|
||||
* 仍会请求旧 chunk 导致 "Failed to fetch dynamically imported module"。
|
||||
* 此时自动刷新页面,让浏览器获取新 index.html 中的新 chunk 引用。
|
||||
*/
|
||||
export function lazyRetry<T extends ComponentType<any>>(
|
||||
factory: () => Promise<{ default: T } | { [key: string]: T }>,
|
||||
): React.LazyExoticComponent<T> {
|
||||
return lazy(async () => {
|
||||
try {
|
||||
const m = await factory()
|
||||
// 统一为 { default: T } 格式
|
||||
if ('default' in m) return { default: m.default }
|
||||
// named export 模式:取第一个导出作为 default
|
||||
const firstKey = Object.keys(m)[0]
|
||||
return { default: m[firstKey] }
|
||||
} catch (err: any) {
|
||||
// 仅对动态导入失败自动刷新,避免其他错误误触发
|
||||
if (
|
||||
err &&
|
||||
(err.message?.includes('Failed to fetch dynamically imported module') ||
|
||||
err.message?.includes('Importing a module script failed') ||
|
||||
err.message?.includes('error loading dynamically imported module'))
|
||||
) {
|
||||
// 防止无限刷新:用 sessionStorage 标记,仅刷新一次
|
||||
const key = 'lazyRetry:' + (err.message.match(/[\w-]+\.js/)?.[0] || 'unknown')
|
||||
if (!sessionStorage.getItem(key)) {
|
||||
sessionStorage.setItem(key, '1')
|
||||
window.location.reload()
|
||||
// 返回一个永不 resolve 的 Promise,等待页面刷新
|
||||
return new Promise<{ default: T }>(() => {})
|
||||
}
|
||||
sessionStorage.removeItem(key)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user