fix(desktop-runtime): 修复桌面端重装后仍命中旧 UI 缓存

- 启动打包版时按 UI buildId 检测并清理 renderer 缓存
- 记录 lastSeenUiBuildId,避免每次启动都重复清缓存
- 调整 SPA 静态资源缓存策略,index.html/200.html/_payload.json 禁止缓存
- 保留 _nuxt 哈希资源长期缓存,减少必须在卸载时删除数据后才生效的问题
This commit is contained in:
2977094657
2026-03-11 13:11:39 +08:00
Unverified
parent b001596fcb
commit 3587ea4eaa
2 changed files with 91 additions and 4 deletions
+60
View File
@@ -7,6 +7,7 @@ const {
globalShortcut,
dialog,
shell,
session,
} = require("electron");
let autoUpdater = null;
let autoUpdaterLoadError = null;
@@ -465,6 +466,34 @@ function getDesktopSettingsPath() {
return path.join(dir, "desktop-settings.json");
}
function getPackagedUiDir() {
if (!app.isPackaged) return null;
try {
return path.join(process.resourcesPath, "ui");
} catch {
return null;
}
}
function readPackagedUiBuildId() {
const uiDir = getPackagedUiDir();
if (!uiDir) return "";
try {
const indexPath = path.join(uiDir, "index.html");
if (!fs.existsSync(indexPath)) return "";
const html = fs.readFileSync(indexPath, { encoding: "utf8" });
const match =
html.match(/buildId:"([^"]+)"/) ||
html.match(/\/_payload\.json\?([^"'&<>\s]+)/) ||
html.match(/data-src="\/_payload\.json\?([^"]+)"/);
return String(match?.[1] || "").trim();
} catch (err) {
logMain(`[main] failed to read packaged UI build id: ${err?.message || err}`);
return "";
}
}
function loadDesktopSettings() {
if (desktopSettings) return desktopSettings;
@@ -476,6 +505,9 @@ function loadDesktopSettings() {
ignoredUpdateVersion: "",
// Backend (FastAPI) listens on this port. Used in packaged builds.
backendPort: DEFAULT_BACKEND_PORT,
// Tracks the packaged UI build so we can invalidate Chromium's HTTP cache
// after upgrades without wiping user data/localStorage.
lastSeenUiBuildId: "",
};
const p = getDesktopSettingsPath();
@@ -539,6 +571,33 @@ function setIgnoredUpdateVersion(version) {
return desktopSettings.ignoredUpdateVersion;
}
async function refreshRendererCacheForPackagedUi() {
if (!app.isPackaged) return;
const nextBuildId = readPackagedUiBuildId();
if (!nextBuildId) return;
const prevBuildId = String(loadDesktopSettings()?.lastSeenUiBuildId || "").trim();
if (prevBuildId === nextBuildId) return;
try {
const ses = session?.defaultSession;
if (ses) {
await ses.clearCache();
try {
await ses.clearStorageData({ storages: ["serviceworkers"] });
} catch {}
}
logMain(`[main] cleared renderer cache for UI build change: ${prevBuildId || "(none)"} -> ${nextBuildId}`);
} catch (err) {
logMain(`[main] failed to clear renderer cache for UI build change: ${err?.message || err}`);
}
loadDesktopSettings();
desktopSettings.lastSeenUiBuildId = nextBuildId;
persistDesktopSettings();
}
function parseEnvBool(value) {
if (value == null) return null;
const v = String(value).trim().toLowerCase();
@@ -1614,6 +1673,7 @@ function registerWindowIpc() {
async function main() {
await app.whenReady();
await refreshRendererCacheForPackagedUi();
Menu.setApplicationMenu(null);
registerWindowIpc();
registerDebugShortcuts();