将静态资源作为服务器:关于 Static 和 Server 的思考
overreacted by
将静态资源作为服务器:关于 Static 和 Server 的思考
2025年5月8日 Pay what you like
RSC 指的是 React Server Components(React服务端组件)。
然而,虽然这篇博客是用 RSC 构建的,但它却是从 Cloudflare CDN 静态提供的,使用的是他们免费的静态托管计划。我的成本正好是零。
零。
这怎么可能呢?
这些不是 React Server Components 吗?
过去,“server” 和 “static” 框架被认为是不同的工具。 例如,你可能会使用 Rails 或 PHP 来开发 “server” 应用程序,但如果你想生成一个 “static” HTML+CSS+JS 网站,你可能会使用 Jekyll 或 Hugo。
但是,现在越来越多的框架支持 “server” 和 “static” 输出模式。 这是基于一种事后看起来很明显的见解:你可以使用任何 “server” 框架,通过在构建过程中运行它的 “server”,并向它发出生成每个页面的请求,然后将响应存储在磁盘上,从而获得一个 “static” 站点。 手动执行此操作会很麻烦,这就是为什么较新的框架倾向于开箱即用地支持此操作。
我将这些框架称为“混合”框架。 从概念上讲,它们是遵循请求/响应模型的 “server” 框架,但可以选择 “static” 输出。
有时,专注于一个用例并完美地解决它使专业化变得有价值。 但我不认为这种情况正在发生。 我不知道 “static” 工具 仅凭 “static” 本身就能为开发人员或最终用户增加任何价值。 这并不意味着 “static” 工具不好,但我看不到 偏爱 它们的任何理由。 另一方面,我看到了偏爱“混合”框架的几个具体理由。
首先,“混合” 方法减少了工具的碎片化 —— 既然重叠如此之大,为什么要有两个生态系统? 区别仅仅在于代码 何时 运行。
“混合” 方法还为你提供了更大的灵活性和更精细的粒度。 它不会将你锁定在特定的方法中。 事实上,现在可以选择按路由进行 “server” 或 “static” 渲染。 你可以从一个完全 “static” 的站点开始,然后在以后添加一个 “server” 页面来显示一些动态内容。 或者,你可以从一个 “server” 站点开始,然后添加一些 “static” 的营销页面。 你的项目,有些是完全 “static” 的,有些是 “server” 的,可以共享代码和插件。 并且可以说,请求/响应的思维模型本身感觉很自然和直观。
这种方法与 RSC 无关。 例如,Astro 不是 一个 RSC 框架,但它 是 一个“混合”框架。 它默认生成 “static” 站点,但你可以选择加入 “server” 功能,例如 API routes 和 on-demand rendering.
当然,RSC 也适用。
我的博客是用 Next.js 构建的,它默认发出 “static” 站点。 事实上,我正在使用 output: "export"
选项 强制 执行此操作,该选项禁用任何需要 “server” 的功能 —— 而我没有 “server”。 如果我尝试使用任何 “server” 功能,我的 “static” 构建将会失败,这正是我在这种情况下想要发生的事情。
换句话说,这个 React Server Component 在部署期间的构建时运行:
export default async function Home() {
const posts = await getPosts();
return (
<div className="relative -top-[10px] flex flex-col gap-8">
{posts.map((post) => (
<Link
key={post.slug}
className="block py-4 hover:scale-[1.005] will-change-transform"
href={"/" + post.slug + "/"}
>
<article>
<PostTitle post={post} />
<PostMeta post={post} />
<PostSubtitle post={post} />
</article>
</Link>
))}
</div>
);
}
你可以在我的主页上看到它的输出。 await getPosts()
调用从文件系统读取 —— 它既不是某种客户端获取,也不是某种服务器运行时代码。 这个 Server Component 在我的静态博客的 部署期间 运行。
是的,当我们 “静态” 运行它们时,我们说 “React Server components” 令人困惑。 但我已经解释过,任何 “server” 框架 已经 是一个 “static” 框架。 你只需要提前命中它并将它的响应保存到磁盘。
所以让我们一起同意克服这一点。
我们编写的代码完全相同。
“Static” 是提前运行的 “server”。
Pay what you like Discuss on Bluesky · Edit on GitHub overreacted