「翻译不是代码,是数据。」——作者在第一部分写下这句话时,确信自己已经解决了问题。直到他发现:改一个西班牙语的标题,要跑完整套部署流程。
承诺与裂缝
![]()
最初的架构足够优雅。翻译存在Cloudflare键值存储(KV)里,边缘缓存,用内容哈希(Content-based Hashing)失效。翻译版本号——整个语言包的SHA哈希——作为构建时常量打进Worker,嵌入每个缓存键。
改字符串→重新算哈希→旧缓存自动失效。干净、确定、内容驱动。
但生产环境暴露了真相:哈希常量活在Worker包里,更新哈希等于重建整个应用。翻译以数据形态存储,却以代码形态失效。
这种耦合很隐蔽。系统能跑,甚至跑得不错,但 quietly contradicts 设计初衷。
三次失败的解耦尝试
作者记录了三个中间方案,每个解决一个问题,又暴露下一个。
尝试一:wrangler deploy --var
Cloudflare CLI支持部署时注入变量,看似能把版本号外置。但底层仍是完整Worker重新部署——只是换了个入口。没有解决"改翻译要重建"的核心矛盾。
尝试二:版本号存KV,每次请求读取
把TRANSLATIONS_VERSION放进KV,请求时实时获取。解耦成功,但代价是每个边缘请求都多一次KV读取。对于高流量场景,这是不可接受的延迟税。
尝试三:KV版本号+短TTL缓存
给KV读取结果加短时缓存(TTL),减少回源。但Cloudflare的边缘节点遍布全球,短TTL意味着大量节点频繁重新验证。规模上去后,缓存命中率波动明显。
三个方案都在"解耦部署"和"请求性能"之间摇摆,无法兼得。
转向:从聪明地设计缓存键,到显式地失效缓存
最终方案换了个思路。不再依赖缓存键的不可预测性来间接失效,而是直接调用Cloudflare的缓存清除接口(Purge API)。
这个API通常用于静态资源管理——刷新CDN上的图片、JS文件。作者把它借来管理国际化内容:翻译更新时,精确清除受影响的缓存条目,而非重建Worker。
关键设计:缓存键回归简单可预测的结构(如`lang:es|page:home`),失效操作由外部系统显式触发。Worker代码不再随翻译变动而变动。
新旧架构的取舍
作者保留了原始实现作为v1分支,承认它仍有适用场景:
• 部署在*.workers.dev子域名的项目(Purge API不可用)
• 不想管理API令牌的小型项目
• 翻译更新极少的个人项目
但对于自定义域名、翻译迭代频繁的场景,Purge API方案是更干净的解耦。
判断
这个案例的价值不在于技术细节,而在于揭示了一类常见的设计陷阱:我们把"不重新部署"当作目标,却忽略了部署的隐性成本正在转移。
哈希嵌入Worker的方案看似免除了缓存管理,实则把成本转嫁给了发布流程——每次翻译更新都是全量重建。而Purge API方案显式承担了缓存管理的复杂度,换取了翻译迭代的独立性。
对于需要快速迭代多语言内容的团队,显式管理缓存失效是更可持续的债务。评估你的翻译更新频率,再决定为哪种复杂度买单。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.