文件夹里有一个做好的页面,就是没有链接。我们把它发布到 Cloudflare Workers 上,把整个流程交给 Claude Code:搭一个 skill,让发布和更新都变成一句简单的请求。

1. 静态站点用的 Cloudflare Workers 是什么

Workers 这个词听起来像"跑在服务器上的程序",这话没错,但不是全部:您可以给 Worker 挂上一个文件夹,服务器就会像普通托管一样把里面的文件原样发出去,一行代码都不用写。

对于一个由 HTML、CSS 和图片组成的页面,这种模式就够用了。文档里把这个文件夹叫 static assets,静态资源,在项目设置里它只占一个字段,就是那个填路径的字段。

Cloudflare 通过自己的服务器网络分发文件,并把它们缓存到离访客更近的地方。

Worker 没有代码,这很正常

只挂了一个文件夹的 Worker,什么都不会运行。以后可以给它加程序,文件夹照样留在原地 - 但那是另一回事,那时的账单也不一样了。

2. 这要花多少钱

对静态文件的请求是免费的,数量也不受限制。这是套餐的条款,不代表没人统计访问量。

那大家常说的那个数字 - 每天 10 万次请求,从哪儿来的?那是对 Worker 脚本调用次数的限制,脚本就是服务器上的那个程序。一个只挂了文件夹的页面没有脚本,自然不会计入这个额度。

对文件的请求不计费,而唤醒 Worker 脚本的请求计入每日额度访客对文件的请求文件已发出请求唤醒脚本脚本已运行不计费计入每日额度
计数器只统计唤醒了程序的那一次请求

图中上面那条路径对应我们的页面:文件发出时不调用任何服务器程序。下面那条路径要等以后加了 Worker 脚本才用得上。

免费套餐也是有限制的,只不过限制的是另一件事,是您发布的东西的大小:

限制免费套餐
单次部署的文件数20,000
单个文件大小25 MB
每个账户的 Worker 数100

对于带十来张图片的页面,这些限制通常绰绰有余。开始一个大项目之前,去查一下Cloudflare 最新的条款:限制可能会变。顺便说一句,单文件 25 MB 听起来很宽裕,直到您想放第一段视频为止。

3. 账户

在 cloudflare.com 上注册很常规:邮箱和密码,然后收一封确认邮件。免费套餐不需要绑卡。也不用添加自己的域名 - 服务会主动提出这一项,但那属于产品的另一半,是给已有网站做保护和加速的功能。

登录之后,您要找的板块叫 "Workers & Pages",位置不太显眼:在左侧菜单里,先是 Build 分组,里面是 Compute,再往里才是 "Workers & Pages"。控制台会不时调整布局,如果这条路径下找不到这个板块,就按名字搜:左上角的搜索框用 Ctrl + K 打开。名字里的两个词对应 Cloudflare 的两款产品;您要的是前半部分 Workers,不用特意选什么,自然就会进到那里。

第一次部署时还会碰到一件事:Cloudflare 会让您给账户选一个子域名。您所有的项目都会挂在这个子域名下,地址由两部分拼成 - 项目名加上您的子域名:

my-landing.example-account.workers.dev
|          |               |
|          |               Cloudflare 的公共域名
|          您账户的子域名
项目名

这个名字以后改起来很麻烦,所以第一时间想到的名字最好先别急着填。

4. 第一次部署

先简单看一眼在控制台里发布是什么样子。这一步是可选的,只是先熟悉一下服务:如果您想直接让智能体来部署,并一直用同一个地址,可以跳到下面的准备工作。

这一点对两种方式都成立

您交出去的永远是整个文件夹,里面的主页面必须正好叫 index.html,并且放在根目录:

landing/          <- 交出去的就是这个文件夹
  index.html      <- 主页面,名字是必需的
  wrangler.jsonc  <- 智能体会在第一次部署前创建它
  style.css
  img/
    hero.png

这是默认规则:请求里没写文件名时,服务器就从对应文件夹里发出 index.html。嵌套也是同样的道理 - about/index.html 会在地址 /about/ 上打开。

这时不会出现任何文件列表:如果根目录里没有 index.html(比如您把上一层文件夹交了出去,它就落到了嵌套的那一层),访问链接得到的就是一个 404 错误。

发布之前,先检查一遍选中文件夹里的内容:里面的文件都会变成公开的。把不打算公开的个人文件和草稿挪出去。

手动通过控制台

项目区域里有个按钮,用来新建项目。接下来会让您交出文件:可以选一个文件,也可以选整个文件夹。上传、确认之后,Cloudflare 就把它们部署好,并返回一个链接。这里按钮的名字和界面的顺序改起来比文章更新还勤,所以抓住意思,别死记标签:新建项目、交出文件、拿到地址。

打开拿到的地址 https://…workers.dev,检查一下页面和图片。用同一台电脑就能做这件事。手机则适合再检查一下能不能正常访问以及移动端的显示效果。

通过控制台发布之后,本地不会留下任何配置文件。我们这个例子里的 skill 不会自己把文件夹和这样的项目关联起来:没有配置文件,它就会想出一个新名字,产生第二个地址。Cloudflare 允许通过 Wrangler 更新已有的 Worker,但这需要您自己另外配一个指向该 Worker 名字的配置文件。

要让智能体来做,需要准备什么

为了以后的发布,我们来搭一个 skill。准备工作只需要在您的电脑上做一次。

需要的软件不多。账户您已经有了,还需要 Node.js - 用命令 node -v 检查,如果找不到这个命令,就得先装上它。wrangler 本身不用装:npx 到时候会自己下载最新版。

  • 账户
  • wrangler login
  • wrangler deploy
  • 链接

示意图上的第二步是登录,值得先把它解决掉,别的事都往后放:

npx wrangler login    # 会打开浏览器,里面有个确认按钮

请在终端里执行这条命令。要是漏了这一步,整个流程会在第一次运行时就卡在这儿,看上去像是 skill 坏了,其实跟它一点关系都没有。想确认是否登录成功,用命令 npx wrangler whoami - 它会显示您是以谁的身份登录的。

走这条路线,通过浏览器登录就够了。API 令牌放在文末的可选延伸内容里讲。

示意图上的第三步,npx wrangler deploy,将由智能体从页面所在的文件夹里运行。我们先给它定好准备配置和发布的规则。

5. 自己的部署 skill

只有一个页面的时候,在聊天里说一句就够了。可一旦有了第二个、第三个、第十个 - 每次都得跟智能体重复同样的事:取哪个文件夹、项目叫什么名字、设置文件怎么处理。到第三次就烦了。

skill 该做到哪些事

五个步骤,每一步都解决一个具体问题,不是为了凑数加进去的:

  1. 拿到指定的文件夹,确认 index.html 就在它的根目录里。这是个成本很低的检查,能在部署之前而不是之后,抓住最常见的那个错误。
  2. 确定项目名 - 从文件夹名推导出来,而不是每次都问一遍。
  3. 看看文件夹里,index.html 旁边,有没有 wrangler.jsonc 文件。没有 - 创建;有 - 从里面取名字,什么都不改写。
  4. 从这个文件夹里运行部署,运行前先把命令显示出来。
  5. 返回公开地址,并提醒您用它检查页面和图片。

项目名来自文件夹

这是整个流程里最关键的决定,恰恰是不能留给智能体临场发挥的那一步。如果没有规则定死名字,智能体就会自己编一个 - 下次又编出另一个。结果就是多出一个地址不同的第二个项目,第一个还悬在那儿没人管。

规则很简单:文件夹名就是项目名。Worker 名字里只能有小写拉丁字母、数字和连字符,所以其余的字符 - 点、空格、下划线 - 都换成连字符,末尾再加一个由四个随机字符组成的短后缀:

landing/                 ->  landing-42c2
my.first.page/           ->  my-first-page-8e10
portfolio-2026/          ->  portfolio-2026-b7a3

加后缀是为了让不同项目里同名的文件夹不会占用同一个地址。它只在创建设置文件时生成一次,而且必须由命令生成,不能由智能体凭空想:不然它就会照抄示例里的后缀,读过同一篇文章的人全都会撞到同一个后缀上。之后这个后缀就一直从配置文件里读取。这正是 skill 要先看现有配置、再决定写不写东西的原因。

已部署项目的名字不改

在已有的配置文件里改 name 字段,不是改名。Cloudflare 会开出一个新项目,地址也是新的,旧项目还带着旧链接留在那儿继续活着 - 就是您已经发给别人的那个链接。

所以流程里才把这件事单独列成一步:配置文件在 - 名字从里面取,别碰它。

设置文件由智能体来写

智能体把项目名和发布设置写进 wrangler.jsonc,好让部署运行时终端里不用问任何问题。配置文件就放在 index.html 旁边,所以里面指向文件的路径就是一个点,意思是"就是这个文件夹":

{
  "name": "landing-42c2",
  "compatibility_date": "2026-09-07",
  "assets": { "directory": "." }
}

compatibility_date 字段决定平台在指定日期上的兼容行为。对新配置,智能体会填上当天的日期,这是Cloudflare 文档推荐的做法;再次发布时则保留原来的日期。

把配置文件放到上一层、跟文件夹平级,不是个好主意:这个文件名是固定的,一个目录里只能有一份,第二个文件夹要么覆盖掉第一个的配置,要么顶着第一个的名字发布出去。放在文件夹内部,每个项目都自成一体,部署就直接从这个文件夹里运行。

这种放法有个副作用:配置文件跟页面在同一个文件夹里,会跟着一起上传到托管平台,也能通过链接直接打开。里面没有任何秘密 - 一个名字、一个日期、一个点 - 要是介意,可以在旁边放一个 .assetsignore 文件,把不想发布的内容列进去。

有三条规则值得在任务里明说,不然智能体猜不到:

  • 没有文件 - 创建它,并展示写入的内容;
  • 已有文件 - 名字和日期照原样保留,哪怕今天的日期不一样;
  • 只有内容真的变了才重写文件。

值得随手备好的四句请求

第一句是给 skill 本身的任务。它比其余几句都长,因为这是唯一一次要把整个流程完整描述出来:

搭一个 skill,用来把静态页面部署到 Cloudflare Workers。
放到这个项目的 .claude/skills/ 里。
最后展示创建出来的 SKILL.md 的路径,以及显式调用这个 skill 的方式。

先读一下 Cloudflare 关于 Workers 和 static assets
的最新文档:命令和配置字段可能已经变了。
如果下面的描述和文档对不上,告诉我,
不要不声不响地自己改。

在 skill 的描述里列出它应该被触发的短语,
至少要有:"发布这个文件夹"、"重新发布"、"部署到 Cloudflare"。

流程:拿到一个文件夹,检查根目录里有没有 index.html。
项目名从这个文件夹的名字推导:只保留
小写拉丁字母、数字和连字符,其余的(空格、
下划线、大写字母、非拉丁字符)都换成连字符。
末尾加一个连字符,后面跟一个四位字符的后缀。
后缀不自己编,而是用命令获取:
node -e "console.log(crypto.randomUUID().slice(0,4))"
wrangler.jsonc 配置文件放在被发布的文件夹内部,
在 index.html 旁边,里面的 assets.directory 等于 "."。
如果没有配置文件 - 就创建它:name、compatibility_date、
assets.directory。新配置的 compatibility_date 用今天的日期,
格式是 YYYY-MM-DD。展示写入的内容。
如果有配置文件 - 名字和日期从里面取,不改写。
只有内容真的变了才重写这个文件。
如果配置文件存在,但 assets.directory 指向的不是这个文件夹,
或者配置里有 main 字段 - 停下来说明情况,不运行部署。
如果被要求重新发布,但文件夹里没有配置文件 - 停下来
问一下,不创建新项目。
部署:在项目文件夹里运行 npx wrangler deploy。运行前先展示命令。
回复里返回公开地址,并提醒用它检查
页面和图片。更新时地址要保持不变。
如果没有 Node.js,或者还没登录 - 我会说明情况,
而不是想办法绕过去。
如果账户还没有 workers.dev 子域名 - 我会说明情况:
非交互式部署在这种情况下会失败。

创建完成后,打开智能体展示的文件 .claude/skills/<名字>/SKILL.md:里面应该有上面这些规则。发第二句之前,用智能体展示的方式显式调用刚创建的 skill。如果找不到这个 skill,请让智能体检查路径,以及它在当前项目里是否可用。

第二句是动手前的检查。适合在文件夹第一次部署前用,让您在东西真正上线之前先看一遍计划;如果有好几个文件夹,就对每一个都用一次:

不要创建或修改任何文件,也不要运行 wrangler。只展示
你打算对 landing 这个文件夹做什么:项目名是什么,
会写什么配置,会运行什么命令。

有一点要说明:后缀是在写配置文件那一刻才出现的,所以对于还没有配置文件的文件夹,计划里的名字和实际运行时的名字可能对不上。其余的都会一致。

第三句和第四句才是干活的,整件事就是为了它们:

把 landing 文件夹发布到 Cloudflare Workers。
我改了 landing 里的 index.html。重新发布到 Cloudflare Workers。

第一次发布之后,打开拿到的链接,检查文字和图片。然后在 landing/index.html 里改一句明显的话,发出第四句请求。刷新同一个地址上的页面:应该能看到新的那句话。如果地址变了,请让智能体在下次部署前检查配置文件里的名字。

主线到这里就走完了:skill 建好了,页面发布了,更新也在同一个链接上验证过了。以后每次发布,剩下要做的就是选好文件夹、看一眼智能体的命令。

6. 附加场景

接下来的内容,只有当您需要一次性准备很多文件夹,或者要在不通过浏览器登录的情况下运行部署时,才有必要往下看。

什么时候流程说明就不够用了

skill 说明书这种方式,在文件夹只有几个或几十个的时候都好用。再往上,麻烦就来了:智能体每次都要重新读一遍流程,手动执行一遍 - 到了五十来个文件夹,这样做既慢,效果也未必每次都一样。

这时就该把流程改写成脚本:它自己遍历文件夹,写配置,跳过没有变化的,最后打印一份汇总。skill 并不会因此消失 - 它只是改成调用脚本,而不是自己写配置,部署依然由它自己运行。

脚本也不用您自己写。智能体手里已经有一份详细的流程说明 - 就是您的 skill - 所以这句请求可以很短:

写一个 Python 脚本,做我的部署 skill 里描述的同样的事,
只不过一次处理项目里所有的文件夹。

取出根目录里有 index.html 的文件夹;
不去看 node_modules、.git 和 dist 里面。
对每一个文件夹按我们的规则生成名字,把 wrangler.jsonc
写进这个文件夹。
如果配置已经存在 - 名字和 compatibility_date 从里面取,
只有内容真的变了才重写这个文件。
如果配置读不出来 - 不去动它,说明情况,
跳过这个文件夹。
默认只显示计划,什么都不写;
写入需要一个明确的开关。
需要一个过滤器,只跑选中的文件夹。
脚本只准备配置,不运行部署。
最后打印一张表:文件夹、项目名、做了什么。
如果这份描述里有哪里不清楚 - 问我,不要自己悄悄猜。

先看计划再落笔,能让您在写入之前检查一遍文件夹列表。保留原有的名字和日期,能保护现有配置不被意外改动。脚本本身只准备设置;发布依然是 skill 的活儿。

访问令牌

在自己的电脑上,您已经用 npx wrangler login 登录过了。Wrangler 会保存这次登录状态,智能体的命令也会用它。

如果需要在不通过浏览器登录的情况下自动运行,或者需要更小的权限范围,就该用 API 令牌了。它可以在个人资料里创建:头像、个人资料、API 令牌板块。直接地址是 dash.cloudflare.com/profile/api-tokens。

创建表单看着挺吓人:权限组、资源、各种过滤器。实际上要做的决定只有四个,一半的字段完全可以不去动。

  1. 令牌名字。 半年之后您肯定想不起来它是干嘛的,所以写得实在点:"笔记本上的页面部署",而不是 "token 2"。
  2. 权限。 没必要也不应该一项一项挑。现成模板列表里有个 Edit Cloudflare Workers - 发布需要的一切它都已经收在里面了。
  3. 资源。 把令牌限制在一个账户上,就是您要发布到的那个账户。哪怕您只有这一个账户,也要显式选中它:账户以后可能会变多,而令牌会一直用下去。
  4. 有效期和 IP 过滤。 这些是可选字段。当令牌只用于一个晚上,或者给别人的机器用时,设个有效期是有意义的;日常工作中保持原样就行。
权限不用靠猜

权限组会随时间变化,项目也总有一天会多出点什么 - 存储、数据库、邮件。昨天还能用的令牌突然就不合适了,看起来像是无缘无故被拒绝。

不用慌:遇到这种情况,wrangler 会说清楚它到底缺了哪种访问权限。您可以把这一整行拿给智能体看,问它该往令牌权限里加什么 - 它读服务文档的速度,比您凭记忆想起来要快。

接下来把令牌放进环境变量 CLOUDFLARE_API_TOKEN,账户则放进 CLOUDFLARE_ACCOUNT_ID。环境变量是您机器上的一项设置,程序会自己读取;wrangler 不用您操心就能找到这两个值。变量具体是怎么运作的,该放在哪里才对,这是另一个话题,这里只需要知道它是一个存放的地方,不是聊天记录里的一行字。

命令在哪里运行用什么登录
自己的电脑,手边有浏览器wrangler login
没有浏览器的服务器、别人的机器、自动化运行放在环境变量里的 API 令牌
令牌不要贴进聊天窗口

和智能体的对话会被保存下来,还会经过网络传输,而一个带有 Workers 权限的令牌,能以您的名义发布和删除任何东西。如果智能体问您要令牌,正确的回答是告诉它去哪里读取,而不是把那串字符直接给它。

一个曾经在什么地方露过面的令牌,正确做法是在控制台里吊销它,再重新创建一个。这比猜测有没有人看到过它代价小得多。