fix: 撤销弹窗及强制跳回机制;在 vite 中去除 Chunk 打包 Hash,并给服务端路由补充无 Hash 回退机制,从物理上消灭缓存旧引用导致的死锁 404
This commit is contained in:
parent
1308bf86fd
commit
e2ada92510
|
|
@ -94,11 +94,30 @@ const matchFile = async (request, response) => {
|
||||||
if (fs.existsSync(mappedPath)) {
|
if (fs.existsSync(mappedPath)) {
|
||||||
targetPath = mappedPath
|
targetPath = mappedPath
|
||||||
} else if (cleanPath.startsWith('/assets/')) {
|
} else if (cleanPath.startsWith('/assets/')) {
|
||||||
|
// 如果请求的是带 hash 的旧文件,尝试摘除 -[hash] 请求固定文件
|
||||||
|
const filename = cleanPath.split('/').pop()
|
||||||
|
const parts = filename.split('.')
|
||||||
|
const ext = parts.pop()
|
||||||
|
const nameParts = parts.join('.').split('-')
|
||||||
|
if (nameParts.length > 1) {
|
||||||
|
nameParts.pop() // 移除最后的 hash
|
||||||
|
const baseName = nameParts.join('-')
|
||||||
|
const fallbackPath = dist + '/assets/' + baseName + '.' + ext
|
||||||
|
if (fs.existsSync(fallbackPath)) {
|
||||||
|
targetPath = fallbackPath
|
||||||
|
} else {
|
||||||
response.writeHead(404, { 'Content-Type': 'text/plain' })
|
response.writeHead(404, { 'Content-Type': 'text/plain' })
|
||||||
response.end('Asset Not Found')
|
response.end('Asset Not Found')
|
||||||
resolve(true)
|
resolve(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
response.writeHead(404, { 'Content-Type': 'text/plain' })
|
||||||
|
response.end('Asset Not Found')
|
||||||
|
resolve(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fs.readFile(targetPath, (err, file) => {
|
fs.readFile(targetPath, (err, file) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
|
|
||||||
|
|
@ -48,25 +48,14 @@ router.beforeEach(async (to, from, next) => {
|
||||||
router.onError((error) => {
|
router.onError((error) => {
|
||||||
const pattern = /Failed to fetch dynamically imported module|Importing a module script failed/i
|
const pattern = /Failed to fetch dynamically imported module|Importing a module script failed/i
|
||||||
if (pattern.test(error?.message || '')) {
|
if (pattern.test(error?.message || '')) {
|
||||||
if (window._chunkErrorHandled) return
|
const isReloaded = sessionStorage.getItem('chunk_reload_flag')
|
||||||
window._chunkErrorHandled = true
|
if (!isReloaded) {
|
||||||
|
sessionStorage.setItem('chunk_reload_flag', 'true')
|
||||||
const forceReload = () => {
|
const forceReload = () => {
|
||||||
// 不再重载当前错误路径,直接跳回首页,并带上时间戳跳出 CDN 缓存
|
const url = new URL(window.location.href)
|
||||||
window.location.href = window.location.origin + '/?t=' + Date.now()
|
url.searchParams.set('t', Date.now())
|
||||||
|
window.location.href = url.href
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanAndReload = async () => {
|
|
||||||
// 暴力清空所有的 Cache API,防止 SW 缓存 index.html 等
|
|
||||||
if (window.caches) {
|
|
||||||
try {
|
|
||||||
const keys = await window.caches.keys()
|
|
||||||
for (const key of keys) {
|
|
||||||
await window.caches.delete(key)
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.getRegistrations().then(registrations => {
|
navigator.serviceWorker.getRegistrations().then(registrations => {
|
||||||
for (const registration of registrations) {
|
for (const registration of registrations) {
|
||||||
|
|
@ -78,12 +67,6 @@ router.onError((error) => {
|
||||||
forceReload()
|
forceReload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.confirm('系统检测到版本更新,当前页面数据已过期。点击【确定】立即刷新体验最新版本!')) {
|
|
||||||
cleanAndReload()
|
|
||||||
} else {
|
|
||||||
window._chunkErrorHandled = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
chunkSizeWarningLimit: 2000,
|
chunkSizeWarningLimit: 2000,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
entryFileNames: 'assets/[name].js',
|
||||||
|
chunkFileNames: 'assets/[name].js',
|
||||||
|
assetFileNames: 'assets/[name].[ext]'
|
||||||
|
},
|
||||||
onwarn(warning, warn) {
|
onwarn(warning, warn) {
|
||||||
if (warning.code === 'UNRESOLVED_IMPORT' || warning.code === 'UNUSED_EXTERNAL_IMPORT') return;
|
if (warning.code === 'UNRESOLVED_IMPORT' || warning.code === 'UNUSED_EXTERNAL_IMPORT') return;
|
||||||
warn(warning);
|
warn(warning);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue