fix: 解决动态加载组件报错 (Failed to fetch dynamically imported module) - 配置 index.html no-cache 防旧缓存,增加 CORS 标头及 router.onError 重试

This commit is contained in:
tangxinyue 2026-07-24 15:35:56 +08:00
parent 2aef509c70
commit 42d197dd2d
5 changed files with 28 additions and 13 deletions

View File

@ -96,7 +96,10 @@ const matchFile = async (request, response) => {
fs.readFile(targetPath, (err, file) => { fs.readFile(targetPath, (err, file) => {
if (!err) { if (!err) {
const mimetype = getMimeType(cleanPath) const mimetype = getMimeType(cleanPath)
const responseHeaders = { 'Content-Type': mimetype } const responseHeaders = {
'Content-Type': mimetype,
'Access-Control-Allow-Origin': '*'
}
if (cleanPath.endsWith("-sw.js")) { if (cleanPath.endsWith("-sw.js")) {
responseHeaders["Service-Worker-Allowed"] = '/' responseHeaders["Service-Worker-Allowed"] = '/'
} }
@ -115,7 +118,13 @@ const endIndex = async (request, response) => {
console.log(dist + '/index.html') console.log(dist + '/index.html')
fs.readFile(dist + '/index.html', (err, html) => { fs.readFile(dist + '/index.html', (err, html) => {
if (!err) { if (!err) {
response.writeHead(httpOk, { 'Content-type': 'text/html;charset=utf-8' }) response.writeHead(httpOk, {
'Content-type': 'text/html;charset=utf-8',
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
'Access-Control-Allow-Origin': '*'
})
response.end(html) response.end(html)
logger.info(`${request.method} ${httpOk} ${request.url}`) logger.info(`${request.method} ${httpOk} ${request.url}`)
} }

View File

@ -2,9 +2,9 @@
<div class="status-bar" :class="{ 'dark-mode': theme === 'dark' }" :style="{ 'background-color': bgColor }"> <div class="status-bar" :class="{ 'dark-mode': theme === 'dark' }" :style="{ 'background-color': bgColor }">
<span class="time">{{ time }}</span> <span class="time">{{ time }}</span>
<span class="status-icons"> <span class="status-icons">
<img class="signal" :src="`/status/signal-${theme === 'dark' ? 'dark-' + signal : signal}.png`" <img class="signal" :src="`/src/public/status/signal-${theme === 'dark' ? 'dark-' + signal : signal}.png`"
alt="" /> alt="" />
<img class="wifi" :src="`/status/wifi-${theme === 'dark' ? 'dark-' + wifi : wifi}.png`" alt="" /> <img class="wifi" :src="`/src/public/status/wifi-${theme === 'dark' ? 'dark-' + wifi : wifi}.png`" alt="" />
<div class="battery"> <div class="battery">
<div class="power" :class="{ 'full-power': battery >= 100 }" <div class="power" :class="{ 'full-power': battery >= 100 }"
:style="{ 'background-color': isCharging ? '#2DC752' : 'var(--battery-bg)', width: battery + '%' }"> :style="{ 'background-color': isCharging ? '#2DC752' : 'var(--battery-bg)', width: battery + '%' }">
@ -12,10 +12,10 @@
<div class="percent"> <div class="percent">
<span class="battery-text" :style="{ 'color': isCharging ? '#ffffff' : 'var(--battery-color)' }"> <span class="battery-text" :style="{ 'color': isCharging ? '#ffffff' : 'var(--battery-color)' }">
{{ battery }}</span> {{ battery }}</span>
<img v-if="isCharging" class="charging" src="/status/charging.png" alt="" /> <img v-if="isCharging" class="charging" src="/src/public/status/charging.png" alt="" />
</div> </div>
</div> </div>
<img style="width: 1px;height: 4px;margin-left: 1px;" src="/status/battery.png" alt="" /> <img style="width: 1px;height: 4px;margin-left: 1px;" src="/src/public/status/battery.png" alt="" />
</span> </span>
</div> </div>
</template> </template>

View File

@ -38,7 +38,6 @@ router.beforeEach(async (to, from, next) => {
// 不需要认证的页面,直接放行 // 不需要认证的页面,直接放行
if (!to.meta.requiresAuth) return next() if (!to.meta.requiresAuth) return next()
// 需要认证的页面:如果没有 token 或者 token 已失效,跳回首页并唤起登录框
if (!token || !userStore.tokenValid) { if (!token || !userStore.tokenValid) {
return next({ path: '/', query: { showLogin: 1 } }) return next({ path: '/', query: { showLogin: 1 } })
} }
@ -46,4 +45,11 @@ router.beforeEach(async (to, from, next) => {
next() next()
}) })
router.onError((error) => {
const pattern = /Failed to fetch dynamically imported module|Importing a module script failed/i
if (pattern.test(error?.message || '')) {
window.location.reload()
}
})
export default router export default router

View File

@ -25,8 +25,8 @@
</div> </div>
</div> </div>
<div class="right-works" @click="$router.push('/works')"> <div class="right-works" @click="$router.push('/works')">
<img v-if="worksCount > 0" src="/profile/hasWorks.png" class="folder-icon" /> <img v-if="worksCount > 0" src="/src/public/profile/hasWorks.png" class="folder-icon" />
<img v-else src="/profile/folder.png" class="folder-icon" /> <img v-else src="/src/public/profile/folder.png" class="folder-icon" />
<span>我的作品</span> <span>我的作品</span>
</div> </div>
</div> </div>
@ -67,7 +67,7 @@
</div> </div>
</div> </div>
<div v-else class="empty-state"> <div v-else class="empty-state">
<img src="/profile/empty.png" class="empty-img" /> <img src="/src/public/profile/empty.png" class="empty-img" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -468,7 +468,7 @@ const systemMsgTemplates = ref([
{ label: '+ 添加成功提示', command: '以上是打招呼的消息' }, { label: '+ 添加成功提示', command: '以上是打招呼的消息' },
{ label: '+ 账号安全', command: '对方账号不在常用环境使用,请仔细核实真实身份,涉及汇款、转账等务必电话确认,请保护自身财产和隐私安全。' }, { label: '+ 账号安全', command: '对方账号不在常用环境使用,请仔细核实真实身份,涉及汇款、转账等务必电话确认,请保护自身财产和隐私安全。' },
{ label: '+ 我要投诉', command: "对方账号安全性未知,如涉及金钱交易务必电话确认,保护个人财产和隐私安全。<span style='color: #576B95;'>我要投诉</span>" }, { label: '+ 我要投诉', command: "对方账号安全性未知,如涉及金钱交易务必电话确认,保护个人财产和隐私安全。<span style='color: #576B95;'>我要投诉</span>" },
{ label: '+ 红包领取', command: "<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/wx-chat/receive-tip.png'></img>xxx领取了xxx的<span style='color: #F49738;'>红包</span>" } { label: '+ 红包领取', command: "<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/src/public/wx-chat/receive-tip.png'></img>xxx领取了xxx的<span style='color: #F49738;'>红包</span>" }
]) ])
let msgIdCounter = 1 let msgIdCounter = 1
@ -630,9 +630,9 @@ function onRedpacketStatusChange(status) {
let content = "" let content = ""
const theirName = settings.theirName || '对方' const theirName = settings.theirName || '对方'
if (selectedMsg.value.sender === 'me') { if (selectedMsg.value.sender === 'me') {
content = `<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/wx-chat/receive-tip.png'></img>${theirName}领取了你的<span style='color: #F49738;'>红包</span>` content = `<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/src/public/wx-chat/receive-tip.png'></img>${theirName}领取了你的<span style='color: #F49738;'>红包</span>`
} else { } else {
content = `<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/wx-chat/receive-tip.png'></img>你领取了${theirName}的<span style='color: #F49738;'>红包</span>` content = `<img style='width: 16px;height: 16px;vertical-align: middle;margin-right:7px' src='/src/public/wx-chat/receive-tip.png'></img>你领取了${theirName}的<span style='color: #F49738;'>红包</span>`
} }
messages.value.push({ messages.value.push({