diff --git a/scripts/purge_list.js b/scripts/purge_list.js index 5f3a417e..808faac9 100644 --- a/scripts/purge_list.js +++ b/scripts/purge_list.js @@ -8,7 +8,9 @@ * 即使源站已更新,CDN 仍会发最多 8 天的旧副本**:本次 about.html 就是这样 * 卡在旧副本上(源站 47935B / CDN 41454B)。 * - * 策略:固定入口页(保底,逻辑不变)+ 本次改动过的 content/*.md 对应的输出页。 + * 策略:固定入口页(保底,逻辑不变) + * + 本次改动过的 content/*.md 对应的输出页 + * + **全局性改动(themes/layouts/assets/static/data、hugo/config)时,追加全站所有 HTML**。 * - 输出页靠「frontmatter 的 url / slug / 目录名 / 文件名」推导,并**校验 * public/ 下确实存在该文件**才加入,避免刷不存在的 URL(刷了也无害,但脏)。 * - 拿不到 git 基线(单提交仓库 / 浅克隆)时自动降级:只输出固定入口页。 @@ -49,8 +51,40 @@ const base = process.argv[2] || 'HEAD~1'; let changed = sh(`git -c core.quotepath=false diff --name-only -z ${base} HEAD`).split('\0').filter(Boolean); if (!changed.length) changed = sh('git -c core.quotepath=false diff --name-only -z HEAD').split('\0').filter(Boolean); +// 递归列出 public 下所有 .html +function walkHtml(dir, out = []) { + let entries; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return out; + } + for (const e of entries) { + const p = path.join(dir, e.name); + if (e.isDirectory()) walkHtml(p, out); + else if (e.name.endsWith('.html')) out.push(p); + } + return out; +} + const urls = new Set(FIXED.map((p) => SITE + '/' + p.replace(/^\//, ''))); +// ★ 全局性改动 → 刷新**全部** HTML(2026-10-05 新增) +// 为什么必须这么做:模板用 resources.Fingerprint 给 JS/CSS 生成带 hash 的文件名, +// 而 upx sync 带 --delete(远端不存在的文件会被删)。主题一改,page-only / core 等 +// 包的文件名就变了 → 老指纹文件被删。文章页的 HTML 若还留在 CDN(TTL 8 天), +// 它引用的就是**已被删掉的旧 JS** → 评论区/交互直接断链。 +// 所以凡是会改变「全站 HTML 引用资源」的改动,都必须让所有 HTML 重新拉取。 +const GLOBAL_DIRS = /^(themes|layouts|assets|static|data|archetypes)\//; +const GLOBAL_FILES = /^(hugo|config)\.(toml|yaml|yml|json)$/; +const isGlobal = changed.some((f) => GLOBAL_DIRS.test(f) || GLOBAL_FILES.test(f)); +if (isGlobal) { + for (const p of walkHtml('public')) { + const rel = p.replace(/^public[\\/]/, '').split(path.sep).join('/'); + if (rel) urls.add(SITE + '/' + rel); + } +} + for (const f of changed) { if (!/^content\/.*\.md$/.test(f) || !fs.existsSync(f)) continue; const src = fs.readFileSync(f, 'utf8');