从 Nuxt SSR 到 Worker + R2:一次解耦内容与代码的架构演进

从 Nuxt SSR 到 Worker + R2:一次解耦内容与代码的架构演进 最近,我为 OnlinesTool 完成了一次较大幅度的架构重构。这篇文章最初是迁移收敛时的设计方案,现在它已经全部上线运行,所以我把它更新成了一份实战记录:既保留当时每个阶段的思考与权衡,也补上落地后的真实实现细节、踩过的坑和实测数据。 这个网站最初只是一个纯粹的在线工具站,核心是一批交互型小工具。但为了 SEO 和生态,后来逐步加入了大量**网站目录(Sites)**详情页和 Blog 文章。随着内容规模持续膨胀,一个原本简单的技术选型,慢慢演变成了真正的架构问题。 整个演进过程大致走过了三个阶段: graph LR A["阶段一: Nuxt SSR + Supabase(运行时动态计算)"] B["阶段二: Nuxt 全静态生成 SSG(构建时全量生成)"] C["阶段三: 双引擎分离架构(Nuxt Assets + Worker + R2)"] A -->|"解决 SSR 限流, 却引入 20 分钟 Build"| B B -->|"代码发布与内容发布彻底解耦"| C有意思的是,第二个方案其实已经解决了第一个方案的大部分问题,但最终我并没有停在 SSG 这一步。因为当运行时的问题解决以后,构建时的问题又冒了出来。本文就完整记录这个过程:每一处的权衡、数据链路、最终的实现细节,以及上线之后真实发生的那些故障与修复——方案收敛只是下半场的开始。 一、阶段一:Nuxt SSR + Supabase 的困境 1.1 初始架构 OnlinesTool 部署在 Cloudflare 上。最初的架构是常见的全栈 SSR:页面由 Nuxt 在服务端渲染,Site 和 Blog 的结构化数据存放在 Supabase(PostgreSQL + PostgREST API)。 sequenceDiagram autonumber actor User as 用户 / 爬虫 participant CF as Cloudflare Edge participant SSR as Nuxt SSR (Worker) participant DB as Supabase User->>CF: 发起页面请求 e.g. /zh/sites/atlassianrovo CF->>SSR: 转发到 Nuxt Worker SSR->>DB: 按 slug 查询 Site/Blog 数据 DB-->>SSR: 返回原始数据 SSR->>SSR: Vue SSR 渲染完整 HTML SSR-->>CF: 返回 HTML CF-->>User: 响应页面对开发来说,这套架构很舒服:数据库里新增一条记录,前端马上就能出页面,完全不用重新构建网站。Blog 也是一样的逻辑,从 CMS 的角度看这套架构没有明显问题。真正的麻烦出现在 Cloudflare Worker 的运行时上。 ...

2026-09-06 · 13 min · 2624 words