PAYATHON 2026

Cloudflare 部署无报错,但移动端与 Web 数据不同步,如何排查?

数据阿明

结论:先追踪一次修改的完整路径

“部署成功、控制台无报错”不足以判断问题出在 Cloudflare 缓存、持久化还是 session。部署成功说明部署流程完成,但不能证明业务数据已经保存,也不能证明另一台设备会主动读取更新。

可以用一条测试记录追踪完整路径:

设备 A 修改 → 发出保存请求 → 后端完成写入 → 设备 B 发出读取请求 → 返回新数据 → 页面显示新数据

“强制刷新后有时恢复”提示需要检查读取时机和缓存,但还不足以认定问题出在 edge cache。

1. 确认修改是否真的离开了设备 A

在设备 A 的开发者工具中打开 Network,保留请求记录,然后修改一条容易识别的测试笔记。检查:

  • 是否发出了对应的保存请求,例如 POST、PUT 或 PATCH。
  • 请求中的记录 ID 和修改内容是否正确。
  • 请求实际发往哪个 API 地址。
  • 响应正文是否表示业务保存成功,而不只是 HTTP 状态码为 200。

如果没有保存请求,检查代码是否只更新了页面内存、localStorage 或 IndexedDB。这些本地状态本身不会跨设备同步。还要确认是否存在尚未执行的防抖保存、离线队列或被忽略的异常。

如果请求已经发出,继续到后端核对写入结果。页面立即显示修改可能只是乐观更新,不能证明数据已经持久化。

2. 核对持久化位置和用户身份

找到保存接口实际执行的写入操作,确认数据存在哪里。如果后端只把笔记放进 Worker 模块级变量、数组或 Map,就不能依靠它们实现可靠的跨请求持久化。Workers 不保证两次请求进入同一个实例,实例也可能被回收。参见 Workers 执行模型。

如果已经使用数据库或其他持久化服务,应核对:

  • 保存接口与读取接口是否连接同一个数据库、namespace 和部署环境。
  • 写入是否确实完成;需要保存完成后再返回成功的接口,是否正确等待了写入结果。
  • 两台设备是否对应同一个后端用户 ID、工作区 ID 和记录 ID。

访问同一个页面 URL 不代表访问同一份业务数据。两台设备可能使用不同的匿名 session,前端也可能调用不同的 API 地址。session token 不同可以是正常情况,需要确认后端是否把它们映射到同一个业务账号。

如果没有登录或设备关联机制,数据又按设备生成的匿名 ID 保存,就需要先明确如何跨设备共享同一份数据。

3. 在设备 B 区分“没读取”和“读到了旧数据”

设备 A 保存后,先不要刷新设备 B,观察它是否发出了读取请求。

观察结果下一步检查
没有读取请求页面是否实现轮询、重新聚焦时读取或服务端推送
请求返回旧数据用户身份、存储位置、读取条件和缓存
请求返回新数据,页面仍显示旧内容前端状态更新、客户端数据缓存,以及旧请求是否覆盖新结果
刷新后仍返回旧数据回查写入结果和读取链路,不能只清浏览器缓存

即使后端已经保存,另一台设备上的页面也需要重新请求或接收通知,才能显示变化。

下面的代码可在同源页面的浏览器控制台中辅助检查读取响应。/api/notes 只是示例,必须替换成实际的读取接口:

async function inspectNotes() {
  const response = await fetch('/api/notes', {
    credentials: 'same-origin',
    cache: 'no-store'
  });

  const body = await response.text();

  console.log({
    status: response.status,
    cacheControl: response.headers.get('cache-control'),
    cfCacheStatus: response.headers.get('cf-cache-status'),
    age: response.headers.get('age'),
    body
  });

  if (!response.ok) {
    throw new Error(`Read failed: HTTP ${response.status}`);
  }
}

inspectNotes().catch(console.error);

这个示例适用于使用同源 Cookie 认证的接口。如果应用使用 Bearer token 或跨域 API,应按实际认证方式调整。cache: 'no-store' 用于排查浏览器 HTTP 缓存,不能保证绕过 Service Worker、自定义 CDN 缓存规则或后端缓存。

4. 用响应证据判断缓存在哪一层

检查笔记 API 的响应,而不只是页面 HTML。观察 Cache-Control、CF-Cache-Status、Age,以及 Network 中是否显示响应来自浏览器缓存或 Service Worker。

Cloudflare CDN 默认不缓存 HTML 或 JSON,但 Cache Rules 和 Worker 中的自定义缓存逻辑可能改变实际行为。因此,不能仅凭应用部署在 Cloudflare 上就认定 API 被边缘缓存。参见 默认缓存行为。

可以逐层做对照:

  1. 在开发者工具中启用 Disable cache,重新请求同一条记录。
  2. 如果应用注册了 Service Worker,临时启用网络绕过,再比较响应。
  3. 检查匹配 API 路径的 Cache Rules,以及代码中是否使用 Cache API 或框架缓存。
  4. 对需要每次读取最新值的个人数据接口,检查是否适合返回 Cache-Control: private, no-store,并确认没有其他规则强制缓存。

CF-Cache-Status: HIT 是检查该响应缓存路径的线索;没有这个响应头,也不能排除应用内部缓存。每次只改变一个条件,记录响应内容是否变化,才能知道哪个设置产生了影响。

如果实际使用的是 Workers KV,还要单独考虑它的最终一致性:其他网络位置可能暂时读取到旧值,这与浏览器缓存或 HTTP edge cache 是不同的问题。确认使用 KV 后,再沿这个方向调查。参见 KV 一致性说明。

5. 为保存和读取过程添加日志

浏览器控制台看不到 Worker 内部的全部执行过程。如果后端使用 Workers,可在对应项目中确认目标部署环境,再运行:

npx wrangler tail

随后重新执行一次保存和读取,观察服务端日志。也可以通过 Cloudflare 控制台查看实时日志。命令及使用方式见 Workers 实时日志说明。如果使用 Pages Functions,应选择对应部署的 Functions 日志入口。

建议在保存和读取接口记录请求 ID、操作类型、内部用户 ID、记录 ID、目标存储标识,以及写入结果或读出的版本号。如果应用目前没有版本字段,不要假定它存在,可以先通过测试记录的唯一内容核对。避免记录 Cookie、token 和完整笔记正文。

还要检查是否存在 catch 后返回空列表、忽略写入失败或始终返回成功的代码。这些处理会让故障表现为“没有报错,但数据不对”。

排查时应明确断点,例如“保存请求未发出”“两端用户 ID 不同”或“读取响应已更新但页面状态未更新”。找到断点后,再修改对应的保存、认证、缓存或刷新逻辑。

备注:内容仅供参考。