alias 和 --env

已修订更新于

首发于

事情起因很简单。

后台已经部署到 Cloudflare。浏览器打开预览地址,登录成功,跳到 /skills。标签页标题却是:

404 - 后台管理

页面不存在。

可本地同一条路由好好的。侧栏第一项就是技能。账号还是管理员。

于是第一个疑问自然冒出来:

路由明明在,为什么线上说页面不存在?

从一场 404 说起

这套后台拆成两个 Worker。

一个是后台 Web,负责页面和 Cookie 会话。
一个是后台 API,负责 REST。

Web 的 SSR loader 要去拉技能列表。当时的写法很直白:拿环境变量里的公网地址,fetch 过去。

预览环境里,这个地址长这样:

https://feat-admin-api.myaccount.workers.dev/api/admin/skills

我在笔记本上 curl 它,没登录会返回 401。路由在,API 也在。

可从 Web 这个 Worker 里面打过去,得到的是 404。
React Router 把这个 404 当成「当前页面不存在」,于是标签页变成了那行字。

真正的原因在 Fetch 文档里:同账号、同 zone 的 Worker 用全局 fetch 打对方的 workers.dev,请求不会进那个 Worker。它会落到空 origin 上。12

浏览器能打开那个 URL。
Worker 里不行。

所以第二个疑问来了:

两个 Worker 到底该怎么说话?

先换成内网

Cloudflare 给的答案不是再拼一个公网域名,而是 Service Binding。34

调用方 wrangler 里写:

{
  "services": [
    {
      "binding": "ADMIN_API",
      "service": "admin-api",
    },
  ],
}

binding 是自己代码里的名字,env.ADMIN_API.fetch(...)。
service 是对方 wrangler 的 name,不是 URL,也不是自定义域名。

这就像 Compose 里的服务名、K8s 里的 ClusterIP:请求不出公网,也不吃同 zone 那条限制。

我改完之后,404 从「页面不存在」变成了另一件事——预览还在,绑定却指错了人。

两种预览

Builds 设置里,非生产分支的版本命令曾经是:

npx wrangler versions upload --env preview

地址栏里看到的却是:

https://feat-admin-web.myaccount.workers.dev

我下意识觉得:--env preview 就是为了生成这个 feat- 前缀。

错了。

这两个东西长得很像,完全不是一回事。

一个是外号。
一个是分身。

alias 是外号

Preview URL 的格式是:

<alias 或版本前缀>-<WORKER_NAME>.<子域>.workers.dev

所以:

feat-admin-web.myaccount.workers.dev

拆开就是:

脚本还是 admin-web。
生产的 Active Deployment 不会被换成这个版本。
自定义域名 admin.example.com 也不会指过来。

对应的命令是 Builds 默认的那条:7

npx wrangler versions upload

需要固定外号时,再加 --preview-alias feat。

它解决的是:我想看看这个 commit,但别动线上。

env 是分身

--env preview 要 wrangler 里真有一块 env.preview。6

没有的话,Wrangler 仍会按命名环境处理,默认把脚本名变成:

<顶层 name>-<环境名>

也就是 admin-web-preview。

Dashboard 里会多出一个 Worker。
Hyperdrive、R2、Service Binding、vars、secrets,都不会从顶层继承,得在 env.preview 里再写一遍。8

这是长期活着的 staging,不是 PR 预览。

你可以给它另绑一个域名,用另一套数据库,让后台 Web 的分身去调后台 API 的分身。
代价是账号里 Worker 数量翻倍,绑定要手搓配对。

Binding 跟谁

Service Binding 跟的是 Worker 名,不是 Git 分支,也不是 Preview URL。

走 alias 时:

同分支如果也改了 API,预览 UI 看不到那份 API。Binding 不会自动跟到「这个 PR 的 API preview」。

走 --env preview 时:

漏写 service,比 404 更危险:页面能开,数据写进生产库。

域名跟谁

自定义域名跟的也是 Worker 名,不是分支名。

走 alias:

走 --env:

之前那个同 zone 404,就是因为用公网 hostname 当「内网 DNS」。
Binding 不认 hostname。域名只负责人从浏览器走进来。自定义域名上的 Worker 互调,规则又不一样。10

这回怎么选

个人站点、PR 只想看页面:

代价很明确:预览 UI 打的是生产 API。

只有这些情况才值得上 env:

那是在复制一整套基础设施。
别用最重的模型,去解决最轻的问题。

收束

回到那次 404。

页面没有丢。
是两件独立的事叠在一起:

修第一件,用 Service Binding。
修第二件,把版本命令里的 --env preview 拿掉。

以后再看见 feat-admin-web.….workers.dev,我会先拆一下:

前半段是外号,后半段才是它到底是谁。

参考资料

  1. Fetch · Worker to Worker
  2. Compatibility flag:global_fetch_strictly_public
  3. Limits · Worker-to-Worker subrequests
  4. Service bindings
  5. Wrangler services 配置
  6. Preview URLs
  7. Workers Builds 配置
  8. Wrangler environments
  9. Wrangler 配置 · Environments
  10. Versions and deployments
  11. Custom Domains · Worker to Worker

Footnotes

  1. Fetch:同账号 Worker 互调,要么 Service Binding,要么 global_fetch_strictly_public。 ↩

  2. Limits:同 zone 无 binding 的 fetch() 会失败。 ↩

  3. Service bindings:不经过公网 URL,直接调另一个 Worker。 ↩

  4. Wrangler services:service 填目标 Worker 名;带环境时为 <name>-<env>。 ↩

  5. Preview URLs:<alias 或版本前缀>-<WORKER_NAME>.<subdomain>.workers.dev。 ↩

  6. Wrangler environments:--env 部署的是另一套 Worker,不是 Preview alias。 ↩ ↩2

  7. Workers Builds:非生产分支默认 wrangler versions upload;只有 wrangler 里真有 named environment 才加 --env。 ↩

  8. 配置 · Environments:bindings 不继承,要在 env.<name> 里重写。 ↩

  9. Deployment management:改被调 Worker 的代码,不会给调用方自动出新 version;binding 打的是对方当前部署。 ↩

  10. Custom Domains:同 zone 打 Route / workers.dev 会失败;目标挂在 Custom Domain 上则可以。 ↩

评论

可对整篇留言,或划选正文中的句子后评论该段。

登录后即可发表评论。

  • 还没有公开评论。
↑