跳转到内容
搜索文档

使用 Cloudflare 提供定制内容

最后更新 查看 MarkdownAgent 设置

内容协商是从单个 URL 提供资源不同版本的做法,根据最终用户定制体验。常见示例包括以特定语言提供内容(Accept-Language)、为设备优化(User-Agent)或提供现代图片格式(Accept)。

Cloudflare 的全球网络旨在大规模处理此需求。对于提供下一代图片等常见场景,此协商通过专用功能简化。对于更自定义的逻辑,Cloudflare 提供包括 Transform Rules、Snippets、Custom Cache Keys 和 Workers 在内的工具包,为您提供细粒度控制,确保每次向每位用户提供正确内容。


使用查询字符串

Transform Rule 方法在您能创建不同 URL 时很理想,例如根据访问者位置提供内容。

地理位置示例

在此示例中,您运营电子商务站点,希望根据访问者国家以当地货币显示价格。

  1. 在 Cloudflare 仪表板中,前往规则的 Overview(概览) 页面。

    Go to Overview ↗
  2. 选择 Create rule(创建规则),然后选择 URL Rewrite Rule(URL 重写规则) 选项。

  3. 输入描述性名称,例如 Vary by Country - Canada

  4. If incoming requests match...(如果传入请求匹配……) 中,选择 Custom filter expression(自定义过滤表达式)

  5. When incoming requests match...(当传入请求匹配……) 下,创建以下表达式:

    • Field(字段): Country
    • Operator(运算符): equals
    • Value(值): Canada
  6. Then...(则……) 下:

    • 对于 Path(路径),选择 Preserve(保留)
    • 对于 Query(查询),选择 Rewrite to(重写为)Dynamic(动态) loc=ca
  7. 选择 Save(保存)

现在,来自加拿大对 /products/item 的请求将在到达源站或缓存之前被转换为 /products/item?loc=ca,从而创建独立的缓存条目。


图片 Vary

图片 Vary 告知 Cloudflare 您的源站支持哪些变体。Cloudflare 随后分别缓存每个版本,并在不每次联系源站的情况下向浏览器提供正确版本。此功能通过 Cloudflare API 进行管理。

启用图片 Vary

要启用此功能,请使用 API 创建 variants rule。此规则将文件扩展名映射到源站可提供的图像格式。

例如,以下 API 调用告知 Cloudflare,对于 .jpeg.jpg 文件,您的源站可以提供 image/webpimage/avif 变体:

Required API token permissions

At least one of the following token permissions is required:
  • Zone Settings Write
  • Zone Write
Change variants settingbash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/cache/variants" \
	--request PATCH \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--json '{
		"value": {
				"jpeg": [
						"image/webp",
						"image/avif"
				],
				"jpg": [
						"image/webp",
						"image/avif"
				]
		}
	}'

创建规则后,Cloudflare 将为每个图像变体创建独立的缓存条目,从而提升现代浏览器用户的性能。

使用 Snippets 进行程序化缓存

Snippets 是独立的 JavaScript fetch 处理程序,在边缘节点上运行,处理经过 Cloudflare 的请求。它们允许您以编程方式与缓存交互,提供对缓存键和响应行为的完全控制,而无需更改用户可见的 URL。

示例:A/B 测试

在本示例中,您运行由名为 ab-test 的 cookie(值为 group-agroup-b)控制的 A/B 测试。您希望为每个组缓存不同版本的页面。

  1. 在 Cloudflare 仪表板中,前往 Snippets(代码片段) 页面。

    Go to Snippets ↗
  2. 选择 Create Snippet(创建代码片段) 并命名为 ab-test-caching

  3. 粘贴以下代码。它根据 ab-test cookie 修改缓存键,并将响应缓存 30 天。

const CACHE_DURATION = 30 * 24 * 60 * 60; // 30 天

export default {
  async fetch(request) {
    // 根据 A/B cookie 构造新的缓存键 URL
    const abCookie = request.headers.get('Cookie')?.match(/ab-test=([^;]+)/)?.[1] || 'control';
    const url = new URL(request.url);
    url.pathname = `/ab-test/${abCookie}${url.pathname}`;

    const cacheKey = new Request(url, request);
    const cache = caches.default;

    let response = await cache.match(cacheKey);
    if (!response) {
      // 如果缓存中没有,从源站获取
      response = await fetch(request);
      response = new Response(response.body, response);
      response.headers.set("Cache-Control", `s-maxage=${CACHE_DURATION}`);
      // 将响应以自定义键存入缓存
      await cache.put(cacheKey, response.clone());
    }
    return response;
  },
};
  1. 保存并部署 Snippet。
  2. 在 Snippets 仪表板中,选择 Attach to route(附加到路由) 以分配该 Snippet。

自定义缓存键(企业版)

如果您的账户使用企业版计划,自定义缓存键功能提供无代码界面,用于定义缓存键中包含哪些请求属性。

自定义缓存键选项:

  • 按设备类型缓存
  • 查询字符串选项 No query string parameters except
  • 包含标头和值
  • 包含 cookie 名称和值
  • 用户:设备类型、国家/地区、语言

示例:相同 URL,不同内容

如果您的源站根据 Accept 标头在同一 URL 提供不同内容类型(例如 application/jsontext/html),请使用自定义缓存键分别缓存它们。

  1. 在 Cloudflare 仪表板中,前往 Cache Rules(缓存规则) 页面。

    Go to Cache Rules ↗
  2. 选择 Create rule(创建规则)

  3. 输入规则名称,例如 Vary by Accept Header

  4. 设置规则的适用条件(例如特定主机名或路径)。

  5. Cache key(缓存键) 下,选择 Use custom cache key(使用自定义键)

  6. 选择 Add new item(添加新项)

    • Type(类型)Header
    • Name(名称)Accept
    • Value(值):添加每个 value,或留空表示全部。
  7. 选择 Deploy(部署)

此配置根据 Accept 标头值创建独立的缓存条目,遵循您的 API 的内容协商。

使用 Cloudflare Workers 实现高级逻辑

对于复杂的缓存场景,Cloudflare Workers 提供完整的无服务器环境,非常适合在大规模场景下实现自定义逻辑。

示例:设备类型 — 免费/专业/商业版(不含分层缓存)

此 Worker 检测访客使用的是移动设备还是桌面设备,并为每种设备创建独立的缓存条目,确保提供并缓存正确版本的站点。

export default {
  async fetch(request, env, ctx) {
    const userAgent = request.headers.get('User-Agent') || '';
    const deviceType = userAgent.includes('Mobile') ? 'mobile' : 'desktop';

    // 创建包含设备类型的新缓存键 URL
    const url = new URL(request.url);
    url.pathname = `/${deviceType}${url.pathname}`;

    const cacheKey = new Request(url, request);
    const cache = caches.default;

    let response = await cache.match(cacheKey);

    if (!response) {
      console.log(`Cache miss for ${deviceType} device. Fetching from origin.`);
      response = await fetch(request);
      let responseToCache = response.clone();
      ctx.waitUntil(cache.put(cacheKey, responseToCache));
    }

    return response;
  },
};

示例:设备类型 — 企业版(含分层缓存)

此 Worker 检测访客使用的是移动设备还是桌面设备,并为每种设备创建独立的缓存条目,确保提供并缓存正确版本的站点。使用企业版 cf.customCacheKey 功能。

export default {
  async fetch(request) {
    // 1. 从 User-Agent 标头确定设备类型
    const userAgent = request.headers.get('User-Agent') || '';
    const deviceType = userAgent.includes('Mobile') ? 'mobile' : 'desktop';

    // 2. 通过在 URL 后附加设备类型来创建自定义缓存键
    const customCacheKey = `${request.url}-${deviceType}`;

    // 3. 获取响应。Cloudflare 的缓存自动使用
    //    customCacheKey 进行缓存操作(match、put)。
    const response = await fetch(request, {
      cf: {
        cacheKey: customCacheKey,
      },
    });

    // 可选:在返回响应之前修改它
    // 例如,添加标头以指示使用了哪个缓存键
    const newResponse = new Response(response.body, response);
    newResponse.headers.set("X-Cache-Key", customCacheKey);
    return newResponse;
  },
};

示例:缓存 Next.js RSC 载荷

一个常见的挑战是缓存来自 Next.js 等框架的内容。Next.js 使用 RSC(React Server Components)请求标头来区分同一 URL 的 HTML 页面加载和 RSC 数据载荷。以下是处理此问题的最佳方法。

方法一:Transform Rules

最简单的解决方案是创建一条 Transform Rule,检查 RSC 标头并在请求上添加唯一查询参数,从而创建两个不同的可缓存 URL:/page(用于 HTML)和 /page?_rsc=1(用于 RSC 载荷)。

  1. 在 Cloudflare 仪表板中,前往规则的 Overview(概览) 页面。

    Go to Overview ↗
  2. 选择 Create rule(创建规则),然后选择 URL Rewrite Rule(URL 重写规则) 选项。

  3. 输入名称,例如 Vary by RSC Header

  4. If incoming requests match(如果传入请求匹配) 中,选择 Custom filter expression(自定义过滤表达式)

  5. When incoming requests match(当传入请求匹配) 下,手动编辑表达式以检查 RSC 标头是否存在:

    • has_key(http.request.headers, "rsc")
  6. Then(则) 下:

    • 对于 Path(路径),选择 Preserve(保留)
    • 对于 Query(查询),选择 Rewrite to(重写为),选择 Static(静态)_rsc=1
  7. 选择 Save(保存)

方法二:Snippets 或自定义缓存键

或者,使用 Snippets自定义缓存键RSC 标头直接添加到缓存键,而不修改可见 URL。这样可以保持更简洁的 URL,但需要更高级的配置。

这篇文档对您有帮助吗?