fix stale frontend cache in install packages

This commit is contained in:
2026-05-20 02:56:44 +08:00
parent 35cd438018
commit 93aa73ab5e
8 changed files with 389 additions and 8 deletions

View File

@@ -111,6 +111,130 @@ if docker exec "$PROJECT-reactive-resume-1" sh -lc 'APP_DIR=$(cat /tmp/reactive-
fi
docker exec "$PROJECT-reactive-resume-1" sh -lc 'APP_DIR=$(cat /tmp/reactive-resume-app-dir); grep -R "String(t).trim().replace" "$APP_DIR/.output/public/assets"/file-*.js >/dev/null 2>&1' \
|| fail "direct 包未在 file-*.js 下载工具中应用文件名补丁"
curl -fsS "http://127.0.0.1:3004/" >/tmp/reactive-resume-home.html \
|| fail "direct 包首页无法访问"
grep -E '/assets/index-[A-Za-z0-9_-]+-rr[0-9a-z]+\.js' /tmp/reactive-resume-home.html >/dev/null \
|| fail "direct 包首页未改用防缓存的 index 主入口文件名"
curl -fsS "http://127.0.0.1:3004/sw.js" >/tmp/reactive-resume-sw.js \
|| fail "direct 包 sw.js 无法访问"
grep -q 'disable stale PWA caches' /tmp/reactive-resume-sw.js \
|| fail "direct 包 sw.js 未替换为清理旧缓存版本"
if command -v google-chrome >/dev/null 2>&1 && command -v node >/dev/null 2>&1; then
log "使用 Chrome 执行 direct 包首页 JS"
node <<'NODE'
const { spawn } = require("child_process");
const fs = require("fs");
const http = require("http");
const port = 9444;
const userData = "/tmp/reactive-resume-chrome-smoke";
fs.rmSync(userData, { recursive: true, force: true });
const chrome = spawn("google-chrome", [
"--headless=new",
"--disable-gpu",
"--no-sandbox",
`--remote-debugging-port=${port}`,
`--user-data-dir=${userData}`,
"about:blank",
], { stdio: ["ignore", "ignore", "ignore"] });
function request(path, method = "GET") {
return new Promise((resolve, reject) => {
const req = http.request({ host: "127.0.0.1", port, path, method }, (res) => {
let body = "";
res.on("data", (chunk) => body += chunk);
res.on("end", () => resolve({ status: res.statusCode, body }));
});
req.on("error", reject);
req.end();
});
}
async function waitForChrome() {
for (let i = 0; i < 60; i++) {
try {
const res = await request("/json/version");
if (res.status === 200) return;
} catch {}
await new Promise((resolve) => setTimeout(resolve, 100));
}
throw new Error("Chrome remote debugging was not ready");
}
(async () => {
await waitForChrome();
const tab = JSON.parse((await request("/json/new?about:blank", "PUT")).body);
const ws = new WebSocket(tab.webSocketDebuggerUrl);
let id = 0;
const pending = new Map();
const errors = [];
const indexRequests = [];
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.id && pending.has(message.id)) {
pending.get(message.id)(message);
pending.delete(message.id);
return;
}
if (message.method === "Runtime.exceptionThrown") {
errors.push(message.params.exceptionDetails);
}
if (message.method === "Network.requestWillBeSent" && message.params.request.url.includes("index-")) {
indexRequests.push(message.params.request.url);
}
};
await new Promise((resolve) => { ws.onopen = resolve; });
function send(method, params = {}) {
return new Promise((resolve) => {
pending.set(++id, resolve);
ws.send(JSON.stringify({ id, method, params }));
});
}
await send("Runtime.enable");
await send("Page.enable");
await send("Network.enable");
await send("Page.navigate", { url: "http://127.0.0.1:3004/" });
await new Promise((resolve) => setTimeout(resolve, 5000));
const result = await send("Runtime.evaluate", {
expression: "document.body.innerText.includes('A free and open-source resume builder')",
returnByValue: true,
});
ws.close();
chrome.kill("SIGKILL");
if (errors.length > 0) {
console.error(JSON.stringify(errors.map((error) => ({
text: error.text,
url: error.url,
line: error.lineNumber,
column: error.columnNumber,
exception: error.exception?.description,
})), null, 2));
process.exit(1);
}
if (!result.result?.result?.value) {
console.error("Chrome did not render the expected home page text");
process.exit(1);
}
if (indexRequests.some((url) => /\/assets\/index-[A-Za-z0-9_-]+\.js$/.test(url) && !/-rr[0-9a-z]+\.js$/.test(url))) {
console.error(`Chrome still requested stale app shell: ${indexRequests.join(", ")}`);
process.exit(1);
}
})().catch((error) => {
chrome.kill("SIGKILL");
console.error(error);
process.exit(1);
});
NODE
else
log "未找到 google-chrome跳过浏览器级首页 JS 测试"
fi
log "离线检查 arm64/QNAP 镜像布局"
ARM64_DIGEST="$(
@@ -173,6 +297,11 @@ grep -R -F 'replace(/[\\/:*?"<>|]/g' "$ARM64_ASSETS_DIR" >/dev/null \
if grep -R -E "index-[A-Za-z0-9_-]+\\.js\\?v=rr-filename-title" "$ARM64_ASSETS_DIR" >/dev/null 2>&1; then
fail "arm64 补丁错误地给 index 主入口追加了 rr-filename-title 缓存标记"
fi
find "$TMP_DIR/arm64-root/app" -type f -exec grep -qE 'index-[A-Za-z0-9_-]+-rr[0-9a-z]+\.js' {} \; -print -quit \
| grep -q . \
|| fail "arm64 补丁未改用防缓存的 index 主入口文件名"
find "$TMP_DIR/arm64-root/app" -path '*/sw.js' -type f -print0 | xargs -0 grep -l 'disable stale PWA caches' >/dev/null \
|| fail "arm64 sw.js 未替换为清理旧缓存版本"
grep -q 'function generateFilename(prefix, extension)' "$ARM64_FILENAME_ENTRY" \
|| fail "arm64 server entry 未包含 generateFilename"
grep -F 'filename.replace(/[\\/:*?"<>|]/g' "$ARM64_FILENAME_ENTRY" >/dev/null \