---
name: cloudflare-publish
description: Deploy, update, verify, or recover (部署/更新/验证/抓回源码) Cloudflare Workers/Pages static sites with wrangler, including pages.dev post-deploy verification and fetching source back from pages.dev. Invoke when the user wants to put a webpage online, deploy or update a Cloudflare Pages/Workers site, or recover deployed source. Do not use for writing new app features.
---

# Cloudflare 发布与接入（通用版）

前提：已安装 Node.js，并完成一次 `npx wrangler login`（浏览器 OAuth 授权 Cloudflare 账号）。之后所有命令直接 `npx wrangler ...`，无需重复登录。
PowerShell 环境，路径含中文/空格时必须加引号。中国大陆网络下命令行访问 Cloudflare API 通常需要代理，见下。

## 网络铁律（踩过坑，务必遵守）

- 命令行 curl 测 **workers.dev 走代理**：`curl.exe -x http://127.0.0.1:7897 ...`（端口按本机代理实际值修改）。
- 命令行 curl 测 **pages.dev 必须直连**：`curl.exe --noproxy "*" ...`。走代理会把 css/js 响应污染成与 index.html 等长（如 2703B/1277B）的 HTML 回退页，哈希比对必假阳性。
- 每次抓取加缓存击穿参数 `?cb=<随机数>` 或 `?x=...`。
- 判断资源真假：看 **Content-Type + 大小**；大小等于 index.html 且 content-type 为 text/html = SPA 回退，不是真文件。浏览器访问两类域名一般都正常。
- 哈希校验时显式加 `-H "Accept-Encoding: identity"`，否则拿到的是 br/gzip 压缩字节，哈希必假 DIFF（压缩后大小还可能恰好与其他文件接近，极具迷惑性）。
- **Pages 部署后有全球边缘收敛窗口（实测可达 5-10 分钟）**：期间同一资源会在「旧回退页 / 新真文件」间逐请求摆动，表现为一会儿 text/html 1277B 一会儿 text/css 10662B。不要据此时的结果下「部署残缺」结论；等收敛后用 identity 编码全量哈希复核（全部一致才算完）。必要时再推一次部署加速刷新。
- 开了 SPA 回退的 Pages 项目：不存在的路径（如 /nope.js）也返回 200 + index.html，因此「200 状态码」不能证明资源存在，必须比对 Content-Type/内容/哈希。

## 部署命令

Pages 直传（纯静态站；从含 index.html 的目录上传）。新项目先创建，再部署：

```powershell
npx wrangler pages project create <pages项目名> --production-branch=main
npx wrangler pages deploy "<站点目录绝对路径>" --project-name=<pages项目名> --branch=main --commit-dirty=true
```

查项目名与域名：

```powershell
npx wrangler pages project list
```

Worker（含 assets 与 D1 绑定，在含 wrangler.toml 的目录内执行）：

```powershell
npx wrangler deploy
```

D1 建表/改表（远程库；`--file` 必须用绝对路径，相对路径会读文件失败）：

```powershell
npx wrangler d1 execute <db-name> --remote -y --file="<绝对路径>\schema.sql"
# 临时查询：
npx wrangler d1 execute <db-name> --remote --command "SELECT ..."
```

含 Pages Functions 的项目：必须在项目目录内执行（cwd 下有 `functions/`），部署日志出现 `Uploading Functions bundle` 才算带上服务端；`wrangler pages dev` 本地调试同理（v4 已无 `--functions` 参数，functions 按 cwd 解析，日志出现 `Compiled Worker successfully` 才生效）：

```powershell
npx wrangler pages dev . --port 8790
```

查 Pages 项目绑定/密钥名（密钥值不可见，同名重部署即沿用，无需知道原值）：Cloudflare REST API `GET /accounts/<account-id>/pages/projects/<名>`，读 `deployment_configs.production.d1_databases / kv_namespaces / env_vars`（用本机 wrangler 配置文件里的 oauth_token；REST 调用走代理）。

## 部署后验证（不要只信部署成功提示）

直连抓生产域名 + 随机参数，grep 新内容标志（新导航名/函数名/新资源），确认 Content-Type 与大小正确。重点核对：

1. index.html 内容为最新版（含本次改动的标志字符串）。
2. 引用的 css/js 全部为真文件（非 SPA 回退页）。
3. 边缘收敛窗口内结果摆动属正常，等收敛后全量复核。

## 从 pages.dev 抓回源码（无本地源码时）

1. 直连下载 `index.html`，解析其中的 link/script/manifest 引用。
2. 递归补齐：ES module 要顺 `import './x.js'` 爬完整依赖树；解析 `manifest.webmanifest` 的图标、`sw.js` 的预缓存清单、CSS 里的 `url(...)`。
3. 每个文件用 Content-Type + 大小 + 哈希三重确认（见网络铁律），SPA 回退会伪装成 200。
4. **Pages Functions 源码无法从线上取回**——只能验证接口行为；服务端逻辑丢失需重写。
5. 抓回后即获得可直传部署的完整目录；若本机另有源码，逐文件哈希比对确认是否同一版本。

## iframe 接入其他应用（门户模式）

1. 先查目标站响应头：无 `x-frame-options` 且无 CSP `frame-ancestors` 才可嵌。
2. 宿主页面 CSP 必须显式加 `frame-src https://目标域名 ...`，否则被拦截。
3. 被嵌的跨站应用要保持登录态，其会话 cookie 必须 `Secure; SameSite=None`。
4. 内嵌页顶部固定放「新窗口打开」（target=_blank rel=noopener）与「返回」；用户浏览器若拦截第三方 Cookie，用新窗口兜底。
5. 完成后必须浏览器实测：iframe 加载、iframe 内登录保持、console 无 `Refused to frame`/CSP 报错。
