地理与可见性
Realm 把 Vercel 边缘的地理信号写到客户端 cookie,驱动 B 站等 region-only UI 微调。不用于语言选择、权限、限流。
proxy.ts 的 GEO_COUNTRY 写入
解析顺序:
- URL
?_geo=US显式覆盖(dev 调试 / 切 VPN 后强制刷新)?_geo=空值 → 清除覆盖- 非两位字母 → 忽略,按未覆盖处理(但仍清 cookie)
- Vercel 边缘
geolocation(request).country(大写两位) - 已有
GEO_COUNTRYcookie(兜底)
返回 { country, overrideAction: 'set' | 'clear' | 'none' },attachGeo() 据此写 cookie:
set且与现有值不同 → 写 12hclear→ 写maxAge: 0删 cookienone→ 不动
客户端读取
_document 内联脚本读 cookie 写 <html data-country="US">(或当前两位码)。hydration 之前同步执行,所以首屏 CSS 就能基于这个属性切换。
lib/region-visibility.ts 是统一 helper:
B 站嵌入 / 友链 / 联系方式等 region-only 内容都走这个 helper,不直接读 cookie / window。
为什么不用 SSR 注入
旧版本(PROBLEM 注释里有记录)尝试在 SSG/ISR 共享缓存层通过 x-geo-country 请求头把 country 注入下游 SSR。但 Vercel CDN 缓存会跨访客复用,第一访客的 country 会污染整段缓存窗口,导致 B 站等 region UI 漂移到错误区域。
现方案是只在客户端使用 country。SSG 产物不带任何 country 信号,由客户端 bootstrap 脚本读 cookie 写 <html> 属性。这样:
- SSG 缓存跨访客安全
- 一次刷新就能反映新 geo
- 客户端 JS 不可用时,region UI 退化到「全显示」或「全隐藏」(由各 helper 决定),不漂移
Vercel 之外的部署
@vercel/functions 的 geolocation(request) 在 Vercel 环境之外没有数据,会返回空 country。此时:
- 第一次请求 GEO_COUNTRY cookie 是空串
isRegionVisible()应返回默认(最宽松或最严格,取决于业务)- 后续请求如果 cookie 还在就用 cookie
非 Vercel 部署如果需要 region 数据,需要在 proxy.ts 里替换 geolocation(request) 为等价数据源(CDN header、MaxMind GeoIP2 等),并改 lib/region-visibility.ts 配合。
安全边界
- GEO_COUNTRY cookie 不参与任何权限 / 限流 / locale 决策
- URL 里的
?_geo=覆盖只影响 UI 微调,不影响 revalidate、TOTP、access-grant country字段永远是大写两位码或空串,没有其他格式