TanStack Start 的预渲染、经典 SSR 与 Cloudflare Workers 缓存

8月 11, 2026
Cloud, Frontend, TypeScript, ByAI

AI 参与说明(Agent:/root、/root/tanstack_research、/root/cloudflare_research、/root/repo_style):本文由 Agent 根据 TanStack、Cloudflare 与 PostgreSQL 的官方公开文档协助整理,重点核对 TanStack Start 的构建期预渲染、Cloudflare Workers Caching、Cache API、缓存失效及存储层边界。资料核验于 2026-08-11;TanStack Start 仍处于 RC 阶段,Workers 与存储产品的 API、默认值和限制会变化。示例仅使用公开占位数据;请在上线前按所用版本、套餐和数据一致性要求复核文末一手资料。

适用范围:本文面向使用 React / TypeScript 构建公开站点或全栈 Web 应用的开发者,讨论 TanStack Start 与 Cloudflare Workers 的组合,也适用于理解一般的 SSG、SSR、CDN 缓存和关系型数据库分层。它不把缓存当作权限控制、事务或持久化方案;登录、支付、库存、订单和其他强一致业务必须另行设计数据与安全边界。

先说结论#

TanStack Start 的 prerender(静态预渲染)是在构建期生成 HTML;经典 SSR 是在运行时生成 HTML;Cloudflare Workers Caching 是在运行时复用 HTTP 响应。 三者解决的是不同问题,可以组合,不能互相替代。

  1. 内容在构建时已确定,例如文档、产品介绍、定价页、有限数量的公开文章详情页,优先用 TanStack Start prerender。它把 HTML 放进部署产物,首个访问者也不需要执行 SSR;内容更新通常需要重新构建和部署。
  2. 内容依赖当前请求或实时数据,例如登录后仪表盘、购物车、用户权限、实时价格,使用 SSR 或纯客户端数据请求。SSR 可以读取请求上下文、访问数据库并渲染完整文档,但没有缓存时,每个请求都要消耗运行时和数据源资源。
  3. 运行时结果可被多人安全复用,例如公开文章、公共目录、公共 JSON、昂贵的模板渲染或第三方 API 结果,用 Workers Caching。命中后 Cloudflare 可以直接返回响应而不执行 Worker,减少 Worker CPU、子请求和后端压力;请求本身仍按 Workers 的计费模型计费,不能理解成“命中完全免费”。
  4. PostgreSQL、D1、R2 等才应保存业务事实。缓存只是可重建的副本:它可能过期、被显式清除,也可能因空间和访问热度被提前驱逐。即使 TTL 尚未结束,也必须能在缓存未命中时回到权威数据源。

下面这张图是一个常见的组合,而不是所有请求都会经过的唯一顺序:

flowchart TB
    A["浏览器请求"] --> B{"命中构建期静态产物?"}
    B -->|"是"| C["预渲染 HTML / 静态资源"]
    C --> Z["返回浏览器并 Hydration"]

    B -->|"否"| D{"Workers Caching 命中?"}
    D -->|"是"| E["边缘缓存的 HTTP 响应"]
    E --> Z

    D -->|"否"| F["TanStack Start SSR / Worker 逻辑"]
    F --> G["权威数据源\nPostgreSQL、D1、R2 等"]
    G --> F
    F --> H["带 Cache-Control 的响应"]
    H --> E

这里的关键边界是:预渲染决定“部署前先生成什么”,缓存决定“运行时可复用多久”,数据库决定“什么才是真的”。

1. 先把四层概念拆开#

主要工作典型产物是否应该保存业务真相
构建期预渲染在 CI / 本机构建时运行路由和 SSR,写出静态页面index.htmlabout/index.html否;它是某一时刻的数据快照
经典 SSR收到请求后运行服务端代码并生成 HTML本次请求的 HTML stream / response否;它是读取数据后的表示层
边缘响应缓存按 HTTP key 保存可复用的响应HTML、JSON、图片或重定向副本否;TTL 和保留时间都不等于持久性
权威数据源保存并协调业务状态PostgreSQL 行、D1 数据、R2 对象等是;写入、事务、约束和恢复在这里处理

浏览器缓存又是另一层。Cache-Control: max-age=60 可能同时影响浏览器和共享缓存;s-maxage 可为共享缓存指定不同 TTL。不要因为“浏览器已经缓存”就假定 Cloudflare 也缓存,或反过来假定边缘缓存一定会刷新浏览器。

2. 和经典 SSR 放在一起比较#

这里的“经典 SSR”指没有命中上游响应缓存时,每个初始请求由服务端渲染页面的模型;它不是某个框架专属术语。TanStack Start 支持完整文档 SSR、流式输出、Server Functions 和 Server Routes;初次匹配路由可以在服务端执行 loader 并产生 HTML,浏览器随后 hydrate。路由 loader 默认是同构代码:初始 SSR 时会在服务端运行,客户端导航时也可能在浏览器运行。TanStack Start Overview 执行模型

维度TanStack Start 静态预渲染经典 SSR(未命中响应缓存)Workers Caching
何时生成 HTML / JSON构建时收到请求时首次运行时生成后,后续按缓存策略复用
命中时是否运行应用服务端代码否,通常直接提供静态文件Workers Caching 命中时否;caches.default Cache API 命中时仍会先执行 Worker
数据新鲜度构建时快照;更新需重建,或另配运行时路径通常接近当前数据源TTL、失效策略和缓存键决定;可接受短时旧值才适合
个性化 / 鉴权不适合把用户数据写入静态 HTML最灵活,可按请求、Cookie、身份处理仅缓存真正可共享的表示;私有响应必须绕过共享缓存
主要成本瓶颈构建时间、构建时数据访问、产物体积每次请求的计算、连接和数据库查询首次 miss 的计算与回源;命中可削减 CPU / 回源,但仍有缓存设计与失效成本
常见用途文档、落地页、公开文章账户中心、权限页面、实时业务公共 SSR 页面、公共 API、可复用计算结果

因此,SSR 和缓存不是二选一。更实用的做法通常是:私有或写后必须立刻一致的路径不做共享缓存;公开而可短时陈旧的 SSR 输出加边缘缓存;稳定且已知的公开页面直接预渲染。

3. TanStack Start 的静态预渲染#

TanStack Start 会在构建阶段把选定路由渲染为静态 HTML 文件。它适合提高首屏速度、给爬虫提供完整 HTML,或把站点部署到只会托管静态文件的环境。Static Prerendering

3.1 一个可验证的 React + Vite 配置#

下面假设项目已经安装 @tanstack/react-start、React、Vite 和相应插件。示例故意关闭自动发现和链接抓取,只列出有限的公开 URL,便于控制构建时访问的数据量与产物范围。

// vite.config.ts
import { defineConfig } from "vite"
import viteReact from "@vitejs/plugin-react"
import { tanstackStart } from "@tanstack/react-start/plugin/vite"

export default defineConfig({
  plugins: [
    tanstackStart({
      prerender: {
        enabled: true,
        autoStaticPathsDiscovery: false,
        crawlLinks: false,
        concurrency: 4,
        failOnError: true,
      },
      pages: [
        { path: "/" },
        { path: "/about" },
        {
          path: "/posts/hello-world",
          prerender: {
            // 此页生成 /posts/hello-world.html,而非目录内的 index.html。
            autoSubfolderIndex: false,
          },
        },
      ],
    }),
    viteReact(),
  ],
})

在标准 Vite 输出下,执行构建后可以检查静态结果:

pnpm build
test -f dist/client/index.html
test -f dist/client/about/index.html
test -f dist/client/posts/hello-world.html

预期是三个检查都成功。部署适配器可以改变最终目录,因此生产 CI 应检查自己的实际输出目录,而不是盲目固定 dist/client

这个配置中最值得理解的项是:

  • pages 是明确的具体 URL 列表,不是参数化路由模式。/posts/$slug 不会自动枚举所有 slug;应列出 /posts/hello-world 等具体路径,或让构建期生成的 <a href> 被抓取发现。
  • autoStaticPathsDiscovery: true(默认)会发现静态路由,但带路径参数的路由、下划线布局路由和没有组件的 API 路由会被排除。
  • crawlLinks: true(默认)会从已预渲染 HTML 的链接继续抓取。它适合有限且完全公开的内容树;URL 很多、带搜索参数、会触发昂贵请求或可能触及后台路径时,应该关闭或用 filter 明确排除。
  • autoSubfolderIndex: true(默认)会把 /about 输出为 /about/index.html;某些静态主机要求 .html 形式时可按页改为 false,或使用 outputPath
  • failOnError: true 让构建期数据源失败直接阻断发布。这样比“悄悄发布缺页”更适合公开文档;若刻意改成 false,必须在 CI 额外检查缺失页面。

截至本文核验的 @tanstack/react-start 1.168.42 发布源码,当前可验证的配置入口是同级的 pagesprerender。官方 ISR 页面仍有 prerender.routes 的旧式示例,但该字段不在这一版本的 schema 中;不要直接复制它。应以安装版本的类型、静态预渲染文档对应 schema 为准。

3.2 预渲染时数据从哪里来#

预渲染会运行服务端渲染和相关 loader,所以它的数据库、CMS、API 或 Cloudflare binding 必须在构建环境可访问。部署到 Cloudflare Workers 时,官方特别说明:预渲染发生在构建期,默认会读取本地环境变量、secrets 和绑定存储的数据;若需要生产数据,要明确配置 remote bindings,并在 CI 提供所需环境变量。Cloudflare 的 TanStack Start 指南

这带来两个边界:

  1. 数据更新后,已部署的静态 HTML 不会自己查询 PostgreSQL 或 D1。通常应由 CMS webhook、内容发布流程或 CI 触发重新构建和部署。
  2. 构建环境能读取密钥,不代表页面能输出密钥。任何进入 loader 返回值、HTML、内嵌状态或静态 JSON 的内容都应按“公开数据”审查;不要以构建期 Cookie、管理员 header 或测试账号生成用户私有页面。

3.3 适用与不适用场景#

适合:

  • 帮助中心、API 文档、产品介绍、稳定的营销页、博客和版本化内容。
  • URL 数量有限,或者可以明确列出并可在构建期稳定访问数据源的公开详情页。
  • 需要首个访问者就获得完整 HTML、但不想在每次请求时运行 SSR 的网站。

不适合,或需要分离成其他路由:

  • 登录态仪表盘、订单、管理员页面、个性化推荐、地区/实验强依赖请求的数据。
  • 无限增长且频繁变化的动态详情页;生成时间、第三方 API 压力和产物体积都会随 URL 数增长。
  • 实时库存、短时价格、刚写入就必须读到新值的内容。它们应走 SSR / API,并根据一致性要求选择是否缓存。

TanStack Start 的 SPA mode 也会在构建时产出一个 shell,但它与“为每个路由输出可索引的完整 HTML”不同;不要把 SPA shell 当成静态预渲染的替代品。SPA mode

4. Cloudflare Workers 缓存:先分清三个机制#

“Workers 缓存”在 Cloudflare 中至少可能指三件事。把它们混为同一个 cache,是设计和排障中最常见的误解。

机制缓存检查位置命中后是否执行入口 Worker分布与适用关键限制
Workers CachingWorker 之前否,直接返回缓存响应Worker 私有的两层边缘缓存;适合公开 SSR HTML、公共 JSON、昂贵计算只缓存 fetch() 的 GET / HEAD;Cache Rules 不控制它
Worker 子请求的 zone cacheWorker 内部 fetch() 到 origin 时是;只省 origin 回源适合代理已有源站、利用 zone Cache Rules / Tiered CacheCache Rule 匹配的是改写后的 fetch() URL,不是用户最初 URL
Cache API:caches.defaultWorker 代码内的 match() / put()是,代码先运行再查显式 key、Worker 自己生成的公开响应当前数据中心本地;没有 tiered cache 和并发合并

4.1 首选理解:Workers Caching#

这是当前 Cloudflare 用来缓存 Worker 输出本身 的机制。开启后,请求会先查 Worker 自己的缓存;命中时 Worker 代码完全不执行。它不属于某个 zone:Cache Rules、Cache Response Rules、Page Rules 和 zone 的默认文件扩展名都不会改变它的行为,缓存策略由 Worker 返回的标准 HTTP 响应头决定。Workers Caching

先在 wrangler.jsonc 启用它。当前文档要求 Wrangler 4.69.0 或更高版本;compatibility_date 应替换为实际部署时的日期。配置说明

// wrangler.jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "public-feed",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-11",
  "cache": {
    "enabled": true
  }
}

再让公开 GET 响应明确可缓存:

// src/index.ts
export default {
  async fetch(request: Request): Promise<Response> {
    if (request.method !== "GET" && request.method !== "HEAD") {
      return new Response("Method Not Allowed", { status: 405 })
    }

    return Response.json(
      {
        generatedAt: new Date().toISOString(),
        items: ["TanStack Start", "Cloudflare Workers"],
      },
      {
        headers: {
          // 浏览器最长缓存 60 秒;共享边缘最长缓存 5 分钟。
          "Cache-Control":
            "public, max-age=60, s-maxage=300, stale-while-revalidate=60",
          // 后续可按标签精确清除。
          "Cache-Tag": "public-feed,posts",
        },
      },
    )
  },
}

部署后连续请求两次:

curl -sD - -o /dev/null https://<你的-worker-host>/ | rg -i 'cf-cache-status|cache-control'
curl -sD - -o /dev/null https://<你的-worker-host>/ | rg -i 'cf-cache-status|cache-control'

在未过期且未被驱逐的正常路径上,第一次预期可见 Cf-Cache-Status: MISS,第二次预期为 HIT;响应 body 的 generatedAt 也应相同。这证明第二次没有执行 new Date(),而不是只证明浏览器缓存了页面。

Workers Caching 默认有靠近用户的 lower tier 和汇聚 miss 的 upper tier;同一个 key 的并发冷启动请求会合并,避免突发流量让同一数据源被同时击穿。它特别适合“首次计算较贵、结果可以共享”的页面。但它仍不是免费或无限的:缓存命中减少 Worker CPU 与后端访问,不会让请求计费凭空消失。缓存工作方式与并发合并

以下安全规则比 TTL 更重要:

  • 只有 GET / HEADfetch() 调用会参与 Workers Caching;POST、PUT、DELETE、WebSocket 升级、Cron、Queue、Workflow、Durable Object 调用和自定义 RPC 都会绕过它。
  • Set-Cookie 的响应、某些带 Authorization 的请求会自动 bypass,但不要把自动 bypass 当作访问控制。账户、后台、订单和权限响应应主动返回 Cache-Control: private, no-store,并在服务端鉴权。
  • 默认 key 包含 entrypoint、路径、query、Worker 版本和必要的 ctx.props,但不包含 hostname。同一个 Worker 绑定多个域名且路径相同,可能共享响应;不同租户、语言、权限或格式应使用不同 URL / ctx.props,或显式使用 Vary 与私有响应策略。Cache keys
  • 省略 Cache-Control 不等于表达“不要缓存”。公开和私有路径都应显式声明缓存意图;no-cache 是“可以存但每次要验证”,而不是绝对不存,真正禁止存储应使用 no-store

数据写入后,先让权威存储提交成功,再清除有关响应。Workers Caching 支持按 Cache-Tag、路径前缀或整个 entrypoint 清除,例如在已经鉴权的写入 handler 末尾执行:

// savePost 是你的 PostgreSQL / D1 等持久层写入;此片段只说明顺序。
await savePost(post)
await ctx.cache.purge({
  tags: [`post-${post.id}`, "posts"],
})

这里的 ctx.cache.purge() 只影响调用它的 Worker 和 entrypoint;zone Dashboard / API 的 purge 不会清掉 Workers Caching。不要把 purge endpoint 暴露给匿名用户。Workers Cache purge

4.2 fetch() 的 zone cache:缓存的是上游资源,不是 Worker 本身#

当 Worker 用 fetch() 请求一个 proxied origin 时,这个子请求会经过 Cloudflare 的 zone cache 和可选 Tiered Cache。Worker 仍然会执行,命中只减少“Worker 到 origin”的往返;适合在返回前改写请求、响应或签名,而仍想复用源站内容。

可通过 fetch(..., { cf: { cacheEverything, cacheTtl, cacheTtlByStatus, cacheKey } }) 等 Cloudflare 属性控制子请求,具体可用项与套餐、compatibility date 和调用方式有关,应以 Request / cf API 为准。尤其注意:如果 Worker 改写了 URL,Cache Rule 和单文件 purge 都应针对真正传给 fetch() 的 URL,而不是浏览器地址。Workers 与 zone cache 的交互

4.3 caches.default Cache API:低层、显式、数据中心本地#

Cache API 的写法看起来像浏览器 Cache API,但语义不同。它允许 Worker 手动 match()put()delete(),适合没有传统 origin、由 Worker 聚合或生成的公开响应;但每次请求仍要先进入 Worker,而且条目不会自动复制到其他数据中心,也不参与 tiered cache 或并发 request collapsing。Workers Cache API

以下最小示例可在基本 Worker 中运行。它故意绕开 Cookie / Authorization,并只删除无关的 utm_source 参数;不要为了提高命中率而丢弃会改变响应含义的参数、语言或租户信息。

export default {
  async fetch(
    request: Request,
    _env: unknown,
    ctx: ExecutionContext,
  ): Promise<Response> {
    if (
      request.method !== "GET" ||
      request.headers.has("Authorization") ||
      request.headers.has("Cookie")
    ) {
      return new Response("This example does not share private responses", {
        status: 400,
        headers: { "Cache-Control": "private, no-store" },
      })
    }

    const keyUrl = new URL(request.url)
    keyUrl.searchParams.delete("utm_source")
    const cacheKey = new Request(keyUrl.toString(), { method: "GET" })
    const cache = caches.default

    const hit = await cache.match(cacheKey)
    if (hit) return hit

    const response = Response.json(
      { generatedAt: new Date().toISOString(), path: keyUrl.pathname },
      { headers: { "Cache-Control": "public, max-age=60" } },
    )

    // 让写缓存继续完成,但不阻塞已生成的公开响应。
    ctx.waitUntil(cache.put(cacheKey, response.clone()))
    return response
  },
}

同一数据中心在 60 秒内再次请求相同 URL,预期得到相同的 generatedAt。这个例子不使用 stale-while-revalidate:Cache API 的 put() / match() 不支持 stale-while-revalidatestale-if-errorput() 只接受 GET key,不能缓存 206Vary: * 响应;miss 返回 undefined,不自动回源,因此必须自己设计 fallback。Cache API 限制

5. 缓存依赖什么存储:和 PostgreSQL 等传统后端的区别#

缓存依赖一个能在 miss 时重建数据的地方。对大多数业务,最稳妥的结构不是“把 PostgreSQL 换成 Workers cache”,而是:

flowchart TB
    A["公开读请求"] --> B["Workers Caching\n公开 HTTP 副本"]
    B -->|"HIT"| C["低延迟响应"]
    B -->|"MISS"| D["Worker / TanStack Start SSR"]
    D --> E["Hyperdrive(可选)\n连接池 / 可选查询缓存"]
    E --> F["PostgreSQL\n事务与权威关系数据"]
    F --> D
    D --> B

    G["写请求"] --> H["鉴权 + 事务写入"]
    H --> F
    H --> I["按 tag / path purge"]
    I --> B

5.1 PostgreSQL 仍是事务与一致性的中心#

PostgreSQL 是关系数据库,适合账户、订单、库存、权限、审计记录和具有多表关系的业务事实。它能以事务把多个 SQL 操作组合成全有或全无的操作,并通过 MVCC / 隔离级别处理并发读取与写入;这正是 HTTP 响应缓存不提供的能力。PostgreSQL transactions PostgreSQL concurrency control

把一次 SELECT 的 JSON 或 HTML 放进边缘缓存,不会复制 PostgreSQL 的事务、约束、索引、行锁或读写隔离。缓存 key 也不是数据库主键:一个页面往往依赖多张表、当前语言、分页和权限。任何写入都应先由 PostgreSQL 完成,再根据“哪些公开表示受影响”清除缓存。

5.2 从全球 Worker 访问现有 PostgreSQL:Hyperdrive 是加速层,不是替代品#

若已经使用 PostgreSQL / MySQL,Cloudflare Hyperdrive 可以在 Worker 边缘侧完成连接建立、在数据库附近维护连接池,并可选择缓存可安全复用的只读查询结果。它解决的是全球分布的短生命周期 Worker 与单区域数据库之间的连接开销、连接数和读延迟,不会把数据库迁移或替换为 Hyperdrive。How Hyperdrive works

需要特别谨慎的是查询缓存:Hyperdrive 不会因为应用向 PostgreSQL 写入就自动失效先前的匹配 SELECT。认证、权限、账单、库存、写后立即读和任何不能容忍旧值的路径,应使用同一数据库的 caching-disabled Hyperdrive binding;它仍保留连接池和快速建连优势。依赖 NOW()CURRENT_DATERANDOM() 等非不可变函数的查询也不应作为可缓存查询设计。Hyperdrive query caching

5.3 D1、KV、R2 与 Durable Objects 的位置#

服务它适合保存什么一致性 / 模型边界不能代替什么
PostgreSQL复杂关系、事务、成熟生态和既有业务数据关系模型、事务、MVCC;通常位于一个或少数区域边缘响应缓存
D1Worker 就近使用的结构化 SQL 数据托管 serverless 数据库,采用 SQLite SQL 语义;不是 PostgreSQL 方言的无缝替代HTTP response cache;迁移前要核对 SQL、扩展和容量需求
Workers KV配置、只读多写少的键值数据、可容忍延迟的元数据全球分发但最终一致;其他地点可在 60 秒以上仍读到旧值原子 read-modify-write、强一致权限 / 库存 / 余额
R2图片、附件、视频、归档、训练数据等大对象S3 兼容对象存储;通过 Worker binding / S3 API 直接读写时具有强一致语义多表事务、任意 SQL 查询、CDN cache 的替代
Durable Objects按对象分片的协调、强一致状态、实时房间有稳定对象身份和持久化存储,适合每实体协调全局关系型分析库或大对象存储

D1 是 Cloudflare 的托管 serverless 数据库,使用 SQLite SQL 语义;它可以成为权威数据层,但仍应在它前面按需放 HTTP 缓存。KV 的读性能来自边缘复制与缓存,因此它故意是最终一致的;它不适合需要原子操作或写后立刻在全球可见的安全状态。D1 overview KV consistency

R2 是一个很好的反例:通过 R2 binding 或 S3 API 直接读取对象时,写、删、元数据更新和 list 具有强一致语义;但若读者经 R2 自定义域名的 CDN 缓存访问,旧对象或旧 404 仍可能保持到 TTL、驱逐或 purge。这说明“权威源一致”与“交付缓存立即一致”是两件事。R2 consistency

6. 什么场景该选什么:可落地的组合#

业务场景建议渲染方式缓存策略权威数据与更新方式
产品页、文档、博客prerender静态资源使用长期版本化缓存;内容发布时重建CMS / Git / PostgreSQL 在构建期读取;发布触发 CI
公共商品目录、新闻详情SSRWorkers Caching,短 TTL + Cache-Tag;发布后 purgePostgreSQL;Hyperdrive 可降低连接和可缓存读查询的成本
公共 API 聚合或昂贵转换Worker 运行时生成Workers Caching;若需特殊 key 或本地热点,用 Cache API外部 API、PG、D1 或 R2;失败 / miss 必须能重算
多语言公开页面prerender 或 SSR更推荐把语言放进 URL;若按请求协商,正确设置 Vary: Accept-Language公开翻译内容;不要按 Cookie 共享缓存
登录仪表盘、订单、后台SSR 或客户端数据请求页面和敏感 JSON 使用 private, no-store;只缓存带 hash 的静态 JS / CSSPostgreSQL / D1;服务端做鉴权和事务
上传图片和下载资源直接对象交付或 Worker版本化对象 key 可长缓存;替换同 key 时 purgeR2 / 对象存储;不把 CDN 副本当文件主副本
支付、扣库存、权限变更Server Function / API 写入不缓存写操作;读后必须新鲜时走无缓存路径PostgreSQL / D1 / Durable Objects,按事务与一致性需求选型

一个简单的决策问题很有用:“两个没有关系的用户收到这个结果,会不会都正确?” 如果答案不是稳定的“会”,不要把它放进共享 HTTP 缓存。再问:“缓存消失后,能否从持久数据安全重建?” 如果不能,它就不应该只存在于缓存。

7. 上线前检查清单#

  1. 列出每个路由的数据来源、是否公开、允许旧多久、写入后如何失效,而不是只填一个全站 TTL。
  2. prerender 只列出具体、公开、构建期可访问的 URL;在 CI 中检查关键 .html 是否生成,并禁止私有数据进入构建产物。
  3. 为公开 Worker 响应显式设置 Cache-Control,为私有响应显式设置 private, no-store;检查 CookieAuthorization、locale、query、tenant 和 hostname 是否进入正确的隔离边界。
  4. 先完成 PostgreSQL / D1 / R2 等持久写入,再同步 purge 受影响的 Workers Caching tag 或路径。关键写入和 purge 失败都不应悄悄丢进 waitUntil() 后假定成功。
  5. 对同一路径分别测试匿名、带 Cookie、带 Authorization、不同语言 / query 的响应,确认不存在跨用户命中。
  6. curl -I 或日志检查 Cf-Cache-Status,并把“首次 MISS、命中 HIT、写后 purge、缓存失效后的 fallback”纳入集成测试。

相关阅读#

参考资料(整理于 2026-08-11)#

本文共 8843 字,上次修改于 Aug 11, 2026,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» Expo 技术原理与交付:从 React Native 项目到 EAS 发布

» Expo、React Native 与 Flutter:概念、架构、上架与选型

» React Native 技术原理:从 TypeScript 到原生界面、Fabric 与 Hermes

» Convex 源码导读:开源仓库版图、核心架构与阅读路线

» Sentry 配置实践:前后端项目划分、日志、追踪、Source Map 与 CLI 迁移