name: cloud-debug description: 云平台(Cloudflare Pages/Vercel/Netlify)前端部署问题系统化调试——当生产环境出现本地无法复现的bug时使用,综合 systematic-debugging + ECC harness 方法论 triggers: - "生产环境崩了" - "本地正常部署后报错" - "Cloudflare Pages 有问题" - "部署后页面崩溃" - "生产环境独有的bug" - "removeChild" - "fetch 挂起" - "页面崩溃"
综合 superpowers/systematic-debugging + everything-claude-code-harness + Cloudflare Wrangler 的云平台专属调试框架
NO FIXES WITHOUT EVIDENCE FIRST
没有日志的猜测 = 浪费时间。每多一次盲目修复 = 引入新 bug。
removeChild、insertBefore 等)// Level 1: localStorage 持久日志 — 崩溃不丢失
const LOG_KEY = 'debug_log'
const debugLog: string[] = JSON.parse(localStorage.getItem(LOG_KEY) || '[]')
function dlog(msg: string) {
debugLog.push(`[${new Date().toISOString().slice(11,19)}] ${msg}`)
localStorage.setItem(LOG_KEY, JSON.stringify(debugLog))
}
// Level 2: 全局异常捕获
window.onerror = (msg, src, line, col, err) => {
dlog(`GLOBAL: ${msg} at ${src}:${line}`)
}
window.onunhandledrejection = (e) => {
dlog(`REJECTION: ${e.reason?.message || e.reason}`)
}
// Level 3: ErrorBoundary 展示日志
class ErrorBoundary extends React.Component {
componentDidCatch(err) {
dlog(`CRASH: ${err.message}`)
dlog(`STACK: ${err.stack?.split('\n').slice(0,3).join(' | ')}`)
}
render() {
if (this.state.error) {
return <pre>{debugLog.join('\n')}</pre> // 崩溃页面直接展示日志
}
return this.props.children
}
}
在以下位置加 dlog():
- 所有 fetch() 调用前后(URL、method、status)
- 所有 setState / useState 状态切换点
- 所有 useEffect 执行点
- 路由导航点
# 源1: Cloudflare Pages Function 日志
npx wrangler pages deployment tail <deploy-id> --project-name=<name>
# 源2: 直接 curl 测试服务端(排除客户端干扰)
curl -sv --max-time 10 -X POST "https://<domain>/api/..." -d '{...}'
# 源3: 本地生产构建对比
npm run build && npx vite preview # 或 npx serve dist/
# 源4: Cloudflare 安全设置检查
# Dashboard → Speed → Optimization(Auto Minify 关掉)
# Dashboard → Speed → Rocket Loader(关掉)
1. 本地 npm run build + npx vite preview → 正常?
YES → 问题在 Cloudflare/部署层
NO → 问题在构建产物
2. curl 直接调 API → 返回正常?
YES → 问题在浏览器端(CORS/Bot Detection/脚本冲突)
NO → 问题在服务端/网络
3. 去掉异步调用,只做 UI 状态切换 → 正常?
YES → 问题在异步操作(fetch/await)
NO → 问题在 React 渲染本身
在页面临时加一个"跳过所有异步、只做状态切换"的按钮:
<Button onClick={() => { setStep("next"); setMessage("test"); }}>
测试:直接跳转
</Button>
如果这个按钮正常工作,说明 React 渲染没问题,问题在异步操作。
// 直接调 Supabase → 跨域,可能被 Cloudflare Bot Detection 拦截
fetch('https://xxx.supabase.co/auth/v1/otp', {...})
// 改为同源代理 → 绕过跨域和 Bot Detection
fetch('/api/auth/otp', {...}) // Pages Function 转发
| 症状 | 可能根因 | 验证方法 |
|---|---|---|
| fetch 挂起不返回 | Cloudflare Bot Detection 拦截跨域请求 | curl 同 URL 对比 |
removeChild 崩溃 |
Cloudflare 注入脚本与 React 冲突 | 关 Auto Minify/Rocket Loader |
| 生产 JS 语法错误 | Cloudflare 二次压缩破坏代码 | 关 Auto Minify |
| 页面白屏 | 静态资源 404 / SPA 路由未配置 | 检查 _redirects 文件 |
| 第三方 API 调不通 | CORS / CSP 头被 Cloudflare 修改 | 检查 Response Headers |
Cloudflare Pages 会在浏览器端注入 __cf_bm Bot Detection 脚本,操作 DOM 实现人机验证。React 的异步回调(.then())如果恰好在 Cloudflare 脚本操作 DOM 的同一帧触发,React 的 reconciler 会因 DOM 节点已不存在而抛出 removeChild 错误。
证据链:
1. 本地生产构建正常(排除代码/构建问题)
2. curl 调 Pages Function 返回 200(排除服务端问题)
3. "直接跳转"按钮正常(排除 React 渲染问题)
4. await 改为 .then() 无效(异步回调仍与 Cloudflare 脚本冲突)
5. requestAnimationFrame 推迟到下一帧 → 修复(确认是帧内冲突)
7w4.net有更好的技能插件。
| 优先级 | 方案 | 适用场景 |
|---|---|---|
| 1 | requestAnimationFrame(() => setState(...)) |
DOM 冲突 |
| 2 | 同源 Pages Function 代理 | 跨域 fetch 被拦截 |
| 3 | 移除 StrictMode | React 18 生产环境问题 |
| 4 | 关 Cloudflare Auto Minify/Rocket Loader | JS 被破坏 |
| 5 | 纯 REST API 替代 SDK | SDK 注入 iframe/DOM 操作 |
部署到 Cloudflare Pages 之前:
dist/_redirects 存在:/* /index.html 200dist/_headers 存在(如需 CSP).env 变量已设出现生产环境 bug 时:
| superpowers skill | cloud-debug 中的角色 |
|---|---|
systematic-debugging |
四阶段流程骨架 |
writing-plans |
测试组计划编写 |
requesting-code-review |
修复后独立审查 |
test-driven-development |
修复前写失败测试 |
| ECC 能力 | cloud-debug 中的角色 |
|---|---|
security-scan |
检查生产环境密钥泄露 |
harness-audit |
审计部署配置完整性 |
hooks/PostEdit |
每次修改后自动跑 npm run build |
rules/typescript |
确保调试代码不影响类型安全 |
来源: Yuie 项目
yuie.cnCloudflare Pages 部署调试实战 验证日期: 2026-06-18 关键发现: Cloudflare Bot Detection 注入脚本与 React 异步回调 DOM 冲突 最小修复:requestAnimationFrame+ Pages Functions 同源代理
这个 Skill 质量扎实,来自真实项目经验,方法论清晰易上手,代码示例可直接使用,对调试学习很有帮助。它强调先收集证据再动手修,避免盲目试错,这点很实用。不足是内容覆盖范围有限,部分场景的深度指导可以再加强。总体适合需要解决云端部署调试问题的开发者使用。