This commit is contained in:
1 parent
6ad717533c
commit
6857fe7074
3 files changed
+76
-8
No files matched your search
+4
-8
@@ -92,7 +92,7 @@ steps:
|
|||||||
- pnpm exec wrangler pages deploy .svelte-kit/cloudflare --project-name=blogflare --branch=main
|
- pnpm exec wrangler pages deploy .svelte-kit/cloudflare --project-name=blogflare --branch=main
|
||||||
|
|
||||||
- name: purge-cache
|
- name: purge-cache
|
||||||
image: curlimages/curl:8.1.2
|
image: node:22-slim
|
||||||
depends_on:
|
depends_on:
|
||||||
- deploy-pages
|
- deploy-pages
|
||||||
environment:
|
environment:
|
||||||
@@ -101,16 +101,12 @@ steps:
|
|||||||
CLOUDFLARE_ZONE_ID:
|
CLOUDFLARE_ZONE_ID:
|
||||||
from_secret: CLOUDFLARE_ZONE_ID
|
from_secret: CLOUDFLARE_ZONE_ID
|
||||||
commands:
|
commands:
|
||||||
- |
|
- node scripts/purge-blog-cache.mjs
|
||||||
curl -s -S -X POST "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/purge_cache" \
|
|
||||||
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
--data '{"purge_everything":true}'
|
|
||||||
|
|
||||||
- name: notify-success
|
- name: notify-success
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
depends_on:
|
depends_on:
|
||||||
- deploy-pages
|
- purge-cache
|
||||||
settings:
|
settings:
|
||||||
token:
|
token:
|
||||||
from_secret: TELEGRAM_BOT_TOKEN
|
from_secret: TELEGRAM_BOT_TOKEN
|
||||||
@@ -125,7 +121,7 @@ steps:
|
|||||||
|
|
||||||
🔗 <b>构建详情:</b> <a href="{{ build.link }}">查看 Drone 运行记录</a>
|
🔗 <b>构建详情:</b> <a href="{{ build.link }}">查看 Drone 运行记录</a>
|
||||||
|
|
||||||
🚀 全套改动现已全网完成发布部署!(缓存清理已在后台同步执行)
|
🚀 全套改动现已全网完成发布部署!(博客域名缓存清理请求已成功提交)
|
||||||
when:
|
when:
|
||||||
status:
|
status:
|
||||||
- success
|
- success
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# 项目统计与页面缓存
|
||||||
|
|
||||||
|
后台「设置 → 数据统计」只查询两个配置域名的访问流量:
|
||||||
|
|
||||||
|
- 博客:`CF_DOMAIN`。
|
||||||
|
- R2 附件:后台保存的 `r2.public_domain`。文章中引用的外链图片不纳入统计。
|
||||||
|
|
||||||
|
流量查询使用 `httpRequestsAdaptiveGroups`,按 hostname 筛选且只包含 `requestSource: eyeball`。CDN 请求命中率明确计算为 `HIT / 总请求数`,包含该域名的后台及 API 请求,并另外列出其数量和各缓存状态。它不代表适配器内部 Cache API 的命中率,也不代表 D1 查询比例。旧的全 Zone PV、按日 UV 累加不再用于项目指标。
|
||||||
|
|
||||||
|
查询优先使用最近 30 天;仅当 API 返回时间范围限制或结果达到分组上限时,尝试 7 天、1 天,并显示实际时段。权限不足、字段不支持或数据不完整时显示「统计不可用」,不回退到全 Zone 流量,不将错误当作零流量。
|
||||||
|
|
||||||
|
统计需要部署环境中的 `CF_API_TOKEN`、`CF_ZONE_ID`,Token 需要对应 Zone 的 Analytics 读取权限。两个域名应属于所配置的 Zone;附件域名若属于另一 Zone,可额外配置 `CF_ASSETS_ZONE_ID`,并授予该 Zone 的读取权限。D1 和 R2 资源统计仍分别使用 `CF_ACCOUNT_ID`、`CF_D1_ID`、`CF_R2_BUCKET`。
|
||||||
|
|
||||||
|
## 缓存策略与更新
|
||||||
|
|
||||||
|
复用 `@sveltejs/adapter-cloudflare` 自带的 Cache API,通过服务端 hook 统一设置公开 HTML 的响应头:
|
||||||
|
|
||||||
|
| 内容 | 浏览器 max-age | 边缘 s-maxage |
|
||||||
|
| --------------------------------------------- | -------------- | ------------- |
|
||||||
|
| 首页、归档、分类、标签、系列列表 | 0 | 300 秒 |
|
||||||
|
| 文章详情、独立页面 | 0 | 3600 秒 |
|
||||||
|
| 后台、API、客户端导航 `__data.json`、错误响应 | 不缓存 | 不缓存 |
|
||||||
|
|
||||||
|
公开页面的查询参数完整保留,分页内容不共用缓存键;客户端导航数据实时读取,不缓存可能包含加载错误或部分节点的数据。预览域名不会启用公开页面缓存。构建生成的哈希静态资源维持适配器原有策略。
|
||||||
|
|
||||||
|
公开 HTML 带有 `blogflare-public:<博客 hostname>` 缓存标签。后台及 API 的内容写入完成后,统一调用 Cloudflare 按标签清理,覆盖旧、新 URL、分页及列表关联;每次修改会失效本博客的所有已标记公开页面,静态附件不受影响。Token 还需要该 Zone 的 Cache Purge 权限。清理请求同步等待(10 秒超时);失败不撤销已经保存的内容,会记录日志及 `cache.purge_error`,并在设置页显示警告。清理失败时列表、详情分别以 5 分钟、1 小时 TTL 兜底。
|
||||||
|
|
||||||
|
Cloudflare 按标签清理存在限流,批量写入时应留意后台警告。API 返回成功表示接受清理请求,实际全球失效及并发旧请求的影响仍需线上验证。
|
||||||
|
|
||||||
|
部署流水线改用 `scripts/purge-blog-cache.mjs`,只清理 `wrangler.jsonc` 中 `CF_DOMAIN` 的 hostname,且检查 HTTP 状态和响应的 `success`。它同时移除升级前未带标签的旧页面及旧 `__data.json` 缓存。第一次上线必须完成这一清理步骤;手动部署时也应在设置 `CLOUDFLARE_API_TOKEN`、`CLOUDFLARE_ZONE_ID` 后执行该脚本。不会清空整个 Zone 或清理其他图片域名。
|
||||||
|
|
||||||
|
## 上线验收
|
||||||
|
|
||||||
|
1. 确认统计面板分别显示配置的博客和附件 hostname;不足 30 天或不可用时显示真实原因。
|
||||||
|
2. 同一节点重复读取公开 HTML,结合 `Age`、Workers 日志及 D1 读取量验证内部缓存;不能只看外层 `CF-Cache-Status`。
|
||||||
|
3. 修改文章内容和 slug,检查直接访问、站内导航、旧地址及分类/标签分页;删除文章和修改站点信息也应失效。
|
||||||
|
4. 确认后台、API 和 `__data.json` 均返回 `no-store`,图片仍正常命中。
|
||||||
|
5. 核对部署清理只作用于博客域名。不要把 CDN 综合命中率作为唯一验收标准。
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
|
||||||
|
// Production deployment must also remove old entries that predate Cache-Tag support.
|
||||||
|
const config = JSON.parse(await readFile(new URL('../wrangler.jsonc', import.meta.url), 'utf8'));
|
||||||
|
const domain = new URL(config.vars.CF_DOMAIN);
|
||||||
|
if (
|
||||||
|
domain.protocol !== 'https:' ||
|
||||||
|
domain.pathname !== '/' ||
|
||||||
|
domain.search ||
|
||||||
|
domain.hash ||
|
||||||
|
domain.username ||
|
||||||
|
domain.password ||
|
||||||
|
domain.port
|
||||||
|
) {
|
||||||
|
throw new Error('CF_DOMAIN must be an HTTPS origin');
|
||||||
|
}
|
||||||
|
const token = process.env.CLOUDFLARE_API_TOKEN;
|
||||||
|
const zone = process.env.CLOUDFLARE_ZONE_ID;
|
||||||
|
if (!token || !zone) throw new Error('Missing Cloudflare purge credentials');
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.cloudflare.com/client/v4/zones/${encodeURIComponent(zone)}/purge_cache`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ hosts: [domain.hostname] }),
|
||||||
|
signal: AbortSignal.timeout(15000)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const result = await response.json();
|
||||||
|
if (!response.ok || result.success !== true)
|
||||||
|
throw new Error(
|
||||||
|
`Blog cache purge failed (HTTP ${response.status}): ${JSON.stringify(result.errors || [])}`
|
||||||
|
);
|
||||||
|
console.log(`Cloudflare accepted the cache purge for ${domain.hostname}`);
|
||||||
Reference in new issue
Block a user