LobeHub Landing 迁移 React Router:SSR 只由 URL 决定

💡 原文中文,约2800字,阅读约需7分钟。
📝

内容提要

LobeHub迁移至React Router,通过Cloudflare缓存HTML降低算力成本。核心是确保SSR输出仅由URL决定,划分数据用途,设置分层缓存头,预渲染稳定内容,并移除主题的SSR依赖。验收标准为缓存命中、无回源及主题切换不改变响应。

🔎

延伸解读

缓存头分层:避免两层 CDN 互相干扰

文章指出,浏览器、Cloudflare 和 Vercel CDN 对缓存头的解读不同,若只设置通用 Cache-Control,两层 CDN 会同时参与 revalidation,导致命中行为难以解释。因此,LobeHub 对三层分别声明了不同的缓存头:浏览器使用 `public, max-age=0`,Cloudflare 使用 `Cloudflare-CDN-Cache-Control` 设置 s-maxage 和 SWR,而 Vercel CDN 则统一 `no-store`。这种显式分层避免了缓存所有权的争

数据分类:避免客户端导航回源

迁移到 React Router 后,loader 在客户端导航时可能再次触发并产生 .data 请求。如果将所有服务端 fetch 原样迁入,即使 HTML 可缓存,站内导航仍会持续回源。文章将数据按用途分为三类:首屏不依赖或依赖用户状态的数据下放到客户端 fetch;URL 完全决定且 TTL 内不变的数据进入 loader 并预渲染;需要新鲜度但仅由 URL 决定的数据保留在 SSR loader。这种分类不仅缩小了 .data 响应,也确保了 Cloudflare 缓存的有效性。

主题退出 SSR:消除缓存碎片

旧实现在 SSR 阶段读取 cookie 或 UA 来设置 data-theme,导致同一 URL 产生多份缓存对象,破坏“只随 URL 变化”的前提。迁移后,服务端输出主题无关的 HTML,由内联脚本在客户端根据 localStorage 和 prefers-color-scheme 设置主题。同时,CSS 变量通过带 hash 的 /theme-vars.css 加载,并注意覆盖 antd v6 的 cssVar 作用域。这一做法确保了主题切换不改变 SSR 响应,也避免了 hydration 抖动,是消除缓存

Q&A

LobeHub 迁移到 React Router 的主要目标是什么?

主要目标是通过 Cloudflare 缓存 HTML 来降低算力成本,确保同一个 URL 总是返回相同的 SSR 输出,从而让 Cloudflare 能够缓存并减少回源。

LobeHub 如何确保 SSR 输出只由 URL 决定?

通过划分数据用途、设置分层缓存头、预渲染稳定内容,并移除主题对 SSR 的依赖,确保 cookie、UA 和用户状态不进入响应决定链。

LobeHub 在迁移中如何处理数据获取?

将数据分为三类:首屏不依赖或依赖用户状态的数据在 hydration 后客户端 fetch;URL 完全决定且 TTL 内不变化的数据放入 loader 并预渲染;需要新鲜度但由 URL 决定的数据留在 SSR loader。这样减少了客户端导航的 .data 请求。

LobeHub 如何设置缓存头以避免两层 CDN 冲突?

为浏览器、Cloudflare 和 Vercel CDN 分别设置不同的缓存头:浏览器使用 Cache-Control,Cloudflare 使用 Cloudflare-CDN-Cache-Control,Vercel CDN 使用 Vercel-CDN-Cache-Control 并设为 no-store,避免双重 revalidation。

LobeHub 为什么选择预渲染部分页面?

因为 Blog、docs、about 和 changelog 的默认语言内容完全由 URL 确定,预渲染可以消除第一次访问时的 Function 执行,同时避免构建时间和产物体积随语言数线性膨胀。

LobeHub 如何解决主题切换对 SSR 的影响?

服务端始终输出主题无关的 HTML,通过内联脚本在首次绘制前读取 localStorage 和 prefers-color-scheme 设置主题,CSS 变量由 html[data-theme] 选择,SSR 只引用 var(--ant-*),不再输出颜色字面量。

LobeHub 迁移的验收标准是什么?

验收标准包括:同一 HTML URL 的第二次请求由 Cloudflare HIT;Vercel CDN 不缓存 HTML;站内导航不再用大体积 .data 请求回源;默认语言的稳定内容直接命中 prerender HTML;主题切换不改变 SSR 响应,也不产生 hydration 抖动。

🏷️

标签

➡️

继续阅读