fix: 撤销弹窗及强制跳回机制;在 vite 中去除 Chunk 打包 Hash,并给服务端路由补充无 Hash 回退机制,从物理上消灭缓存旧引用导致的死锁 404

This commit is contained in:
tangxinyue 2026-07-24 16:37:11 +08:00
parent 1308bf86fd
commit e2ada92510
3 changed files with 35 additions and 28 deletions

View File

@ -94,11 +94,30 @@ const matchFile = async (request, response) => {
if (fs.existsSync(mappedPath)) {
targetPath = mappedPath
} 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.end('Asset Not Found')
resolve(true)
return
}
} else {
response.writeHead(404, { 'Content-Type': 'text/plain' })
response.end('Asset Not Found')
resolve(true)
return
}
}
}
fs.readFile(targetPath, (err, file) => {
if (!err) {

View File

@ -48,25 +48,14 @@ router.beforeEach(async (to, from, next) => {
router.onError((error) => {
const pattern = /Failed to fetch dynamically imported module|Importing a module script failed/i
if (pattern.test(error?.message || '')) {
if (window._chunkErrorHandled) return
window._chunkErrorHandled = true
const isReloaded = sessionStorage.getItem('chunk_reload_flag')
if (!isReloaded) {
sessionStorage.setItem('chunk_reload_flag', 'true')
const forceReload = () => {
// 不再重载当前错误路径,直接跳回首页,并带上时间戳跳出 CDN 缓存
window.location.href = window.location.origin + '/?t=' + Date.now()
const url = new URL(window.location.href)
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) {
navigator.serviceWorker.getRegistrations().then(registrations => {
for (const registration of registrations) {
@ -78,12 +67,6 @@ router.onError((error) => {
forceReload()
}
}
if (window.confirm('系统检测到版本更新,当前页面数据已过期。点击【确定】立即刷新体验最新版本!')) {
cleanAndReload()
} else {
window._chunkErrorHandled = false
}
}
})

View File

@ -41,6 +41,11 @@ export default defineConfig({
build: {
chunkSizeWarningLimit: 2000,
rollupOptions: {
output: {
entryFileNames: 'assets/[name].js',
chunkFileNames: 'assets/[name].js',
assetFileNames: 'assets/[name].[ext]'
},
onwarn(warning, warn) {
if (warning.code === 'UNRESOLVED_IMPORT' || warning.code === 'UNUSED_EXTERNAL_IMPORT') return;
warn(warning);