家庭数据中心系列 通过 Cloudflare 实现精准缓存清除:Cache-Tag 与前缀方式实战

1 前言

很多使用 Cloudflare CDN 的朋友经常会遇到这样一个问题:修改了网站的某些内容,但刷新网页后却发现更改并没有立即生效。这时,大家的第一反应往往是去 Cloudflare 仪表盘里点一下 “清除所有内容”

image.png

虽然这样能立刻解决问题,但却有个很大的副作用——所有的静态资源(HTML、CSS、JS、图片等)都会被清除,访客访问网站时不得不重新从源站加载所有内容,这会导致页面变慢、流量浪费,甚至影响 SEO。

实际上,我们很多时候真正想要清除的只是HTML 页面,比如修改了 functions.php、header.php 或 footer.php,导致页面结构发生变化,但 Cloudflare 仍在提供旧的 HTML 缓存,这时候只清除 HTML,而不动 CSS、JS、图片,才是最合理、最精确的做法。

虽然 Cloudflare 仪表盘本身没有提供”只清除 HTML”这种直观选项,但好消息是:现在包括免费用户在内,都可以通过仪表盘提供的 4 种方式 来灵活地清除缓存内容(之前免费用户只能使用 URL 方式,其他 3 种方式曾是 Pro 及以上计划专属)。

目前Cloudflare 支持的 4 种自定义清除缓存的方式:

image.png

在这几种方式中:

  • 按 URL 清除 —— 太繁琐,尤其当你修改了多个页面时,需要一个个列出完整 URL,容易出错,也难以维护。
  • 按主机名清除 —— 又太粗暴,直接清除整个子域下的所有内容,等于”温和版”的清除全部缓存,控制粒度太粗。
  • 按标记和前缀清除 —— 这两种方式则兼顾灵活性和控制力,如果前期在开发中有意识地通过 Tag 或路径前缀对资源进行过合理分组,那么后期运维时只需要指定一个标签或路径前缀就能精准清除相关缓存,避免动辄全站失效。

所以,从长期运维和自动化部署的角度来看,推荐从建站时候就引入 Cache-Tag 或路径前缀设计,这样未来无论通过仪表盘还是 API 操作,都可以优雅地清除缓存内容,而不是”无差别轰炸”。

2 基于缓存标记方式

2.1 缓存标记简介

缓存标记(Cache-Tag) 是 Cloudflare 提供的高级缓存管理功能,它允许用户自己为缓存的内容添加自定义标签,以便更精确地控制缓存的清除。Cache-Tag 是由源站服务器(如 WordPress)在 HTTP 响应头中设置的,当 Cloudflare 获取并这些内容缓存在CDN中时,它会读取并关联这些标签。

通过使用 Cache-Tag,你可以为不同类型的资源(如 HTML 页面、CSS 文件、JS 文件、图片等)打上不同的标签。这样,在需要时,你可以通过标签精确清除这些特定资源的缓存,而不是清除整个站点的缓存。

注:Cache-Tag是给Cloudflare缓存系统看的,和浏览器缓存行为无关。

2.2 在源站添加缓存标记

可以根据不同的源站部署方式和环境,使用不同的方法来添加 缓存标记(Cache-Tag)。下面是几种常见的部署方式和相应的操作方法:


1. WordPress 部署

对于 WordPress 用户,可以通过插件或自定义代码来为响应添加 Cache-Tag,常见的做法是使用 PHP 函数 在 functions.php 文件中设置自定义的 Cache-Tag,或者使用专门支持 Cache-Tag 的缓存插件。

  • 自定义代码:通过在 functions.php 中使用 header() 函数,向 HTTP 响应头中添加 Cache-Tag。例如,可以为特定页面、文章或类别动态生成不同的标签。
  • 插件:一些缓存插件(如 W3 Total CacheWP Super Cache 等)提供了与 Cloudflare 配合的选项,允许你在缓存内容中添加自定义标签。

以自定义代码为例,只需要将以下这段代码添加到functions.php中即可对所有HTML内容设置缓存标记”html-tag”(还是强烈建议使用code snippets来统一管理所有需要插入主题文件的代码):

function add_cache_tags_to_headers() {
    // 仅在前端页面执行,避免后台管理页面
    if (is_admin()) {
        return;
    }

    // 仅对 HTML 页面设置 Cache-Tag
    if (is_page() || is_single() || is_home() || is_archive()) {
        header('Cache-Tag: html-tag');
    }
}
add_action('send_headers', 'add_cache_tags_to_headers');

关键点解释:

  1. 前端页面限定:使用 is_admin() 判断,确保缓存标记仅在前端页面执行,避免后台管理页面不必要地添加 Cache-Tag。
  2. 仅针对 HTML 页面:通过 is_page()、is_single()、is_home()、is_archive() 判断当前页面类型,仅在这些页面类型下添加 Cache-Tag,避免对 CSS、JS 等资源生效。
  3. 直接设置 HTTP 头:省略了数组处理逻辑,直接使用 header(‘Cache-Tag: html-tag’),减少额外的运算,提高代码执行效率。
  4. 精简逻辑,提高可读性:去掉了对 CSS、JS、图片等资源的匹配逻辑,使代码更加清晰易懂,便于维护和调整。

如何验证是否成功?设置之后直接访问源站的时候,可以在浏览器开发者工具的”网络”-“标头”选项卡下HTML页面的响应标头中看到(只有直接访问源站时才能看到):

image.png

HTML 的 Cache-Tag 能生效,是因为 WordPress 通过 PHP 处理页面请求,并在 send_headers Hook 中添加了相应的标记。而 CSS、JS 、图片等静态资源则由 Nginx 或 Apache 直接提供,不会经过 WordPress 的 PHP处理逻辑,因此 send_headers 无法作用于这些文件。

如果要实现CSS和JS的Cache-Tag设置,需要在WordPress搭配的Apache或者Nginx中进行设置,以Apache为例(因为docker方式部署的WordPress就是基于Apache),需要在html/.htaccess中添加如下设置:

# 确保 Apache 版本兼容,防止意外崩溃
<IfModule mod_headers.c>
    <FilesMatch "\.css">
        Header always set Cache-Tag "css-tag"
    </FilesMatch>

    <FilesMatch "\.js">
        Header always set Cache-Tag "js-tag"
    </FilesMatch>

    <FilesMatch "\.(jpg|jpeg|png)$">
        Header always set Cache-Tag "image-tag"
    </FilesMatch>
</IfModule>

然后重启 Docker,就可以对 CSS、JS 以及图片(仅限同一域名下源站中的图片,例如 WordPress 媒体库中的图片)设置对应的 Cache-Tag 了。


2. 使用 Nginx 作为反向代理

如果源站使用 Nginx 作为反向代理服务器,通常需要在 Nginx 配置文件中设置 Cache-Tag。通过根据请求的 URL 路径、请求头、查询参数等条件,Nginx 可以动态地为不同的资源添加 Cache-Tag。

  • 基于 URL 路径:根据请求的 URL 路径来决定使用哪些标签。例如,为所有 /products/ 路径下的页面资源添加 Cache-Tag: product。

Nginx 配置示例:

例如,你想为所有 /products/ 路径下的页面资源添加 Cache-Tag: product:

location /products/ {
    add_header Cache-Tag "product";
}

解释:当请求的 URL 路径以 /products/ 开头时,Nginx 会为响应添加 Cache-Tag: product。这种方式非常适合基于路径的资源分组(如产品页面、分类页面等)。

  • 基于请求头或查询参数:可以根据 HTTP 请求头(例如,User-Agent)或查询参数(例如,?category=xyz)来动态地为不同请求添加不同的 Cache-Tag。

Nginx 配置示例:

如果你希望根据用户的 User-Agent 请求头添加不同的 Cache-Tag:

location / {
    if (http_user_agent ~* "mobile") {
        add_header Cache-Tag "mobile-tag";
    }
    if (http_user_agent !~* "mobile") {
        add_header Cache-Tag "desktop-tag";
    }
}

解释:根据 User-Agent 请求头的值,如果用户是使用移动设备访问,Nginx 会为响应添加 Cache-Tag: mobile-tag;如果是桌面设备访问,则添加 Cache-Tag: desktop-tag。

  • 基于查询参数添加 Cache-Tag

例如,如果 URL 中带有查询参数 ?category=xyz,你希望为所有这类请求添加 Cache-Tag: category-xyz:

location / {
    if ($arg_category = "xyz") {
        add_header Cache-Tag "category-xyz";
    }
}

解释:当请求的 URL 带有查询参数 category=xyz 时,Nginx 会为响应添加 Cache-Tag: category-xyz。这种方式特别适用于根据不同的筛选条件(如商品类别、文章分类等)为不同内容添加标签。


3. 使用 Apache 作为 Web 服务器

如果源站使用 Apache 作为 Web 服务器,通常可以通过 .htaccess 文件来添加 Cache-Tag。Apache 提供了强大的条件判断功能,允许根据请求路径、查询参数或请求头动态地为响应添加自定义标签。这使得在不同情况下精细控制缓存变得更加灵活。

.htaccess 配置示例

  • 基于 URL 路径添加 Cache-Tag

例如,你希望为所有 /products/ 路径下的页面添加 Cache-Tag: product:

<IfModule mod_headers.c>
    <Location "/products/">
        Header set Cache-Tag "product"
    </Location>
</IfModule>

解释:当请求的 URL 路径以 /products/ 开头时,Apache 会为该路径下的所有资源响应添加 Cache-Tag: product。这种方式适用于根据路径结构分组资源,比如为所有产品页面统一添加一个标签。

  • 基于请求头添加 Cache-Tag

如果你希望根据请求头(如 User-Agent)来决定 Cache-Tag,可以使用以下配置:

<IfModule mod_headers.c>
    SetEnvIf User-Agent "mobile" CACHE_TAG=mobile-tag
    SetEnvIf User-Agent "desktop" CACHE_TAG=desktop-tag
    Header set Cache-Tag %{CACHE_TAG}e env=CACHE_TAG
</IfModule>

解释:根据 User-Agent 请求头的值,Apache 会检查是否是移动设备或桌面设备访问。如果是移动设备,添加 Cache-Tag: mobile-tag,如果是桌面设备,添加 Cache-Tag: desktop-tag。这种方式适用于根据访问设备的不同设置不同的缓存标签。

  • 基于查询参数添加 Cache-Tag

如果你希望根据 URL 中的查询参数(例如 ?category=xyz)来为请求添加 Cache-Tag,可以使用以下配置:

<IfModule mod_headers.c>
    RewriteEngine On
    RewriteCond %{QUERY_STRING} category=xyz
    RewriteRule .* - [E=CACHE_TAG:category-xyz]
    Header set Cache-Tag %{CACHE_TAG}e env=CACHE_TAG
</IfModule>

解释:当 URL 查询参数 category=xyz 存在时,Apache 会为该请求响应添加 Cache-Tag: category-xyz。这种方式适合根据特定的查询参数(如商品分类、文章分类等)来区分缓存标记。


4. 使用其他 CDN 或反向代理服务

如果你的站点不使用 Cloudflare,而是其他 CDN 或反向代理服务(如 Fastly、AWS CloudFront 等),可以根据这些服务的文档来添加 Cache-Tag 或类似的标记。大多数现代 CDN 都支持某种形式的缓存标签机制,虽然具体的实现方式可能会有所不同。


2.3 基于缓存标记的CDN内容清除

如果要清除CDN中某个缓存标记对应的分类内容,操作非常简单,只需要在仪表盘的”缓存”-“配置”-“自定义清除”部分:

image.png

选择”标记”,然后输入对应类别的标记进行清除即可:
image.png

3 基于路径前缀方式

如果要清除CDN中某个路径下的内容,操作非常简单,并不需要像缓存标记方式那样先折腾源站半天来打标记,而是只需要在仪表盘的”缓存”-“配置”-“自定义清除”部分:

image.png

选择”前缀”,然后输入对应的前缀进行清除即可:
image.png


如果网站在早期设计阶段就有意识地考虑后期缓存清理的问题,那么通过有规律地规划 URL 路径结构,就相当于提前实现了一个”按目录归类”的机制。这样做的最大好处是:哪怕你没有使用 Cache-Tag 功能,也可以借助 Cloudflare API 提供的 prefix 匹配清除功能,高效地实现逻辑分组的缓存清理。

举个例子,如果你将所有博客文章统一放在 /posts/ 目录下、所有产品页放在 /products/ 下,那么当你发布或更新文章时,只需要通过 API 清除 /posts/ 前缀下的缓存,就可以把相关文章的 HTML、封面图、相关脚本等一并清理,不需要逐条列出 URL。

相比之下,如果 URL 路径设计混乱、无规律,后期就只能一条条指定具体的 URL,既容易遗漏,又增加了维护成本。

这种“结构化路径 = 隐式 Cache-Tag”的设计方式,适合于:

  • 静态博客 / 文档网站:URL 构成通常非常规律;
  • 电商类网站:可以按分类、品牌、活动等设计前缀路径;
  • 多语言网站:可以按语言作为路径前缀,如 /en/、/zh/、/fr/ 等;
  • 大型门户网站:可将不同模块按功能模块分路径,例如 /news/、/events/、/videos/ 等。

换句话说,如果你没有使用 Cache-Tag 的条件,也不愿意修改服务端逻辑,那么”URL 前缀规划良好”就是你运维缓存清理最值得依赖的资产之一,与其说它是种权宜之计,不如说它本身就是一种架构上的远见。


4 使用API清除CDN中特定缓存内容

4.1 概述

有些朋友可能不喜欢频繁地打开 Cloudflare 仪表盘手动操作,尤其是在日常维护或自动部署流程中,这种方式显得既不高效也不现实。而在某些自动化场景中,例如网站发布新文章、更新页面模板、运行 CI/CD 部署脚本时,我们也无法依赖图形界面来清除缓存。这时候,Cloudflare 提供的 API 就显得尤为重要。

通过调用 Cloudflare 的缓存清除 API,我们可以编程式地实现缓存管理,无需登录仪表盘即可精准地清除特定 URL、路径、标签(Cache-Tag)或主机名下的缓存。这种方式不仅灵活,而且非常适合集成到自动化流程中,比如:

  • 在 WordPress 发布文章后自动清除对应页面的缓存;
  • 在部署静态资源后只清除特定路径下的旧资源;
  • 定期清理某类标签下的缓存内容,以保证前端页面的更新能及时反映给访客。

相比”清除所有缓存”这种粗暴的做法,API 的精细控制能力可以有效避免不必要的缓存失效,从而提升网站的性能表现和用户体验。

4.2 通过 API 清除指定类别的 Cache-Tag 缓存内容

4.2.1 前提准备

要使用 API,你需要以下信息:

  • API Token(推荐):具备 Zone.Cache Purge 权限。
  • Zone ID:你的域名在 Cloudflare 中的唯一标识。
  • Account Email(如使用 API Key)。
  • API Endpoint:用于缓存清除的地址。

4.2.2 API 请求结构(清除 Cache-Tag)

请求地址

POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache

请求头(使用 API Token):

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

请求体(按 tag 清除):

{
  "tags": ["html-tag"]
}

4.2.3 curl 调用示例

curl -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/purge_cache" \
     -H "Authorization: Bearer YOUR_API_TOKEN" \
     -H "Content-Type: application/json" \
     --data '{"tags": ["html-tag"]}'

你可以将这条命令加入到你的网站部署脚本、WordPress 钩子(如 publish_post)、CI/CD 流程中,实现在特定事件触发时自动清除缓存。

注1:多个标签 可以同时清除,只需将它们写成数组形式,例如 ["html-tag", "homepage", "footer"]

注2:API Token 权限建议:为了安全,建议创建专用的 API Token,仅授予 Cache Purge 权限,避免使用全局 API Key。

注3: 如果你使用的是 API Key 而非 Token,请使用如下头部替代

X-Auth-Email: [email protected]
X-Auth-Key: your-global-api-key

4.3 通过 API 清除指定路径下的缓存内容

4.3.1 前提准备

要使用 API 清除指定路径下的缓存内容,你需要以下信息:

  • API Token(推荐):具备 Zone.Cache Purge 权限。
  • Zone ID:你的域名在 Cloudflare 中的唯一标识。
  • Account Email(如使用 API Key)。
  • API Endpoint:用于缓存清除的地址。

4.3.2 API 请求结构(清除指定路径下的缓存)

请求地址

POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache

请求头(使用 API Token):

Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

请求体(按路径前缀清除):

{
  "prefixes": ["https://example.com/blog/"]
}

在请求体中,prefixes 数组包含了需要清除缓存的路径前缀,Cloudflare 将根据这些路径前缀清除匹配的所有缓存资源。

4.3.3 curl 调用示例

curl -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/purge_cache" \
     -H "Authorization: Bearer YOUR_API_TOKEN" \
     -H "Content-Type: application/json" \
     --data '{"prefixes": ["https://example.com/blog/", "https://example.com/products/"]}'

你可以将这条命令加入到你的网站部署脚本、WordPress 钩子(如 publish_post)、CI/CD 流程中,实现在特定事件触发时自动清除缓存。

注1:路径前缀清除:通过指定路径前缀(如 /blog/ 或 /products/),可以清除匹配该路径下的所有缓存资源。这比逐个列出 URL 要简洁许多,尤其是当你知道某个路径下的所有资源需要清除时。

注2:多个路径清除:可以同时清除多个路径前缀,只需要将它们写成数组形式,例如:["https://example.com/blog/", "https://example.com/products/"]

注3:API Token 权限建议:为了安全,建议创建专用的 API Token,仅授予 Cache Purge 权限,避免使用全局 API Key。

注4:如果使用的是 API Key:而非 API Token,请使用以下头部进行身份验证

X-Auth-Email: [email protected]
X-Auth-Key: your-global-api-key

5 如何验证Cache-Tag是否生效?

image.png

由上图Cloudflare关于Cache-Tag的官方文档说明可知,在收到源站带有Cache-Tag的响应并返回给网站访客之前,Cloudflare会直接将所有的Cahce-Tag删除(可以理解,本来Cache-Tag就是给CDN供应商看的,和访客无关),因此在访客浏览器的开发者工具中看不到Cache-Tag(所以我在前面的文章中强调了只有直接访问源站才能看到)。

但是这样一来如何验证Cache-Tag是否真的生效了呢?其实很简单,以我的未使用APO而使用了常规页面规则进行缓存的测试站点为例,先设置规则如下:

image.png


使用这条页面规则对测试站点启用缓存,设置为”缓存所有内容 + 边缘缓存 TTL 为 2 小时”。这样配置之后,Cloudflare 的边缘节点会将首页内容缓存 2 小时,但由于未设置浏览器 TTL,浏览器不会将页面内容缓存在本地。

这样做的目的是为了接下来的测试:我会使用”正常重新加载”(非强制刷新)功能重新访问首页。如果浏览器本地也缓存了首页,那么即便 Cloudflare 的边缘缓存已经失效,浏览器仍可能直接从本地缓存读取页面内容,干扰判断。而现在的设置能确保每次加载都必须从 Cloudflare 获取资源,从而更准确地观察和测试 CDN 缓存状态(比如判断 cf-cache-status 是 HIT 还是 MISS)。


正常情况下,访问首页时看到的CF-Cahce-Status的结果是”HIT”:

image.png

这个时候,按照文章前面所讲,先直接在仪表盘缓存的自定义清除的”标记”里清除html-tag标记:

image.png

然后正常重新加载(刷新)页面,这个时候,如果清除html-tag标记成功,缓存里应该是没有这个页面的,所以Cf-Cache-Status的结果应该是”MISS”:
image.png

6 总结

对于一般的个人站长而言,使用了Cache-Tag之后运维工作会高效很多,再也不用含泪”清除所有内容”了,而哪怕是对于使用了APO功能的站长来说,Cache-Tag在很多时候也会发挥奇效,为什么这么说?

一般来说,使用了 APO 其实不需要频繁手动清除缓存,因为 APO 本身就是为了解决 WordPress 的缓存刷新问题而设计的:它会在后台监听 WordPress 的一些典型更新操作,比如发布新文章、更新页面、修改菜单等,在这些事件发生之后,APO 会自动触发对应页面的缓存刷新。也就是说,在大多数情况下,只需要等几分钟到几个小时(Cloudflare 官方说法是”几分钟内”),新的内容就会自动生效,无需人工干预。

不过,这个”自动刷新”并不是实时的,也无法覆盖所有场景。比如你修改了 functions.php、主题模板文件,或者调整了 header/footer 的结构,哪怕这些改动直接影响了页面的最终输出内容,APO 也不会检测到这些变化,更不会自动刷新缓存。这是因为 APO 的缓存刷新机制,本质上是依赖 WordPress 的钩子系统来感知内容变化的——比如更新文章、发布页面、切换主题、保存菜单等等,这些属于 WordPress 内容层面的变更,Cloudflare 可以通过 API 通知来自动清除对应缓存。但像模板文件、插件文件、PHP 逻辑代码的修改,并不会触发 WordPress 的相关事件钩子,Cloudflare 自然也就”看不见”这些改动,缓存内容就可能一直保持旧的状态。

也就是说,这类”结构性修改”场景下,APO 不是”自动刷新得比较慢”,而是”根本不会刷新”,哪怕你等再长的时间都不会生效,除非你手动去清除缓存,或者通过后台做一次内容层面的修改,例如随便改动并保存某篇文章,也能触发 APO 去刷新相关页面(其实这种方式才是最简单的,只是非常的没有技术含量,我不屑于使用,另外这也只能针对模板、结构的调整这一方面的改动,比如修改functions.php)。

因此,对于那些需要频繁调整模板、优化结构或者调试输出逻辑的站点来说,单靠 APO 是不够的,仍需借助”手动清除”功能来确保前台即时呈现最新的内容。而如果你还希望这个”手动清除”尽可能聪明一点、有选择性一些(比如只清除 HTML、只清除某类页面),那么Cache-Tag就是非常棒的工具,当然,提前规划好前缀并配合自定义清除缓存中指定前缀的功能也类似。

分享这篇文章
博客内容均系原创,转载请注明出处!更多博客文章,可以移步至网站地图了解。博客的RSS地址为:https://blog.tangwudi.com/feed,欢迎订阅;如有需要,可以加入Telegram群一起讨论问题。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
       
error:
zh_CN