SSR为什么比SSG更好用

SSR为什么比SSG更好用


为什么只需要 SSR 就够了

SSR(server-side rendering),指在服务器运行时按需渲染页面,之后传送到前端。SSG(server-side generation),指事先编译好 HTML 等静态文件,在用户请求时直接把静态文件传到前端。

说清楚了定义就很容易想到,SSR 能嵌入动态的逻辑,但需要始终运行一个服务器,而 SSG 更适合静态的内容,可以放到 CDN 上。知名的 NextJS 框架便同时支持了 SSR 和 SSG。而后起之秀 Remix 则完全抛弃了 SSG,他们认为这样做有足够多的好处。根据我的体会,在现代 CDN 的加持下,这样做确实有一定的道理。

  • 像 Cloudflare, Vercel 等现代 CDN 都支持 serverless 环境,部署 NodeJS 程序几乎和部署静态文件一样方便。
  • SSG 的好处无非是将静态文件直接部署到 CDN 上,节省服务器资源。而 SSR 通过设置适当的 Cache-Control,也能轻松的将内容缓存到 CDN 上。这样一来其实只有在第一次请求时才会运行 SSR 服务端,几乎和静态文件无异了
  • 不用每次修改静态内容都重新编译、重新部署
  • 一旦抛弃 NextJS 那样区分 SSG 和 SSR 的思路,思维负担就少了很多。缓存的设置完全依赖于 Cache-Control 等 HTML 标准,不需要额外学习一套接口。缓存的问题调试起来也方便很多,当浏览器缓存了不该缓存的请求,你只需要看看你编写的 Response 即可。

举个例子

事实上,Remix 的官方网站就是一个绝好的例子。它的文档就是用 SSR 生成的。很多人会觉得,文档都是静态文字,用 SSG 不是最好吗?Remix 团队解释了这样做的原因。

他们的文档放在 Remix 的源代码仓库里,并没有直接写在官网里。这样文档和源代码放在一起的好处有

  • 阅读代码的时候更有参考性
  • 修改代码时能方便地修改文档
  • git 会自动记录文档的变动,和源代码版本绑定在一起

官网的服务端读取了 Remix 源代码的仓库,通过 SSR 生成文档页面。这样做的好处是:

  • 不用每次修改文档就重新编译和部署整个网站
  • 可以直接从 Remix 源代码库里拿到某一版本的文档,甚至可以直接拿到 dev branch 上最新的文档。这样一来官网可以显示任意 Remix 版本所对应的文档。

文档毕竟不是实时变化的数据,所以他们还做了一些缓存优化

  • 使用 lru-cache 来缓存文档结果。缓存在服务端,所以所有客户端都会受益。
    • timeout 设置为 5 分钟
  • 设置  Cache-Control 为  stale-while-revalidate 。这样可以让 CDN 也缓存
    return json(
      { doc },
      {
        headers: {
          "Cache-Control": "max-age=300, stale-while-revalidate=604800",
        },
      }
    );
    这样一旦文档有任何修改,官网最多只会延迟 5 分钟(max-age=300)显示。