元素的示例:
Fastify 与 Vite 的集成设置为探索各种框架的 SSR 性能提供了理想的试验平台。
在本文中,我们将探讨实现 SSR 所需的最小代码库,并比对五款主要前端库的性能:React、Vue、Solid、Svelte 和 Preact。我们还将探讨 fastify-html(Fastify 的 ghtml 封装器)和通过 @fastify/view 实现的 EJS(Express 的 HTML 模板引擎)等更简单的替代方案。
【第2874期】新时代的 SSR 框架破局者:qwik
我们没有考虑 Next.js、Astro、Qwik 等这样的工具,以及其他的完整框架,因为它们不提供独立的渲染方法。
对于基于 @fastify/vite 的测试,我们使用了以下的示例代码:
import Fastify from 'fastify'
import FastifyVite from '@fastify/vite'
const server = Fastify()
await server.register(FastifyVite, /* options */)
await server.vite.ready()
await server.listen({ port: 3000 })
所有的测试都是在生产版本上进行的,也就是说,在运行 vite build 之后。
唯一例外是 fastify-html 和 ejs 测试,它们不需要 Vite。
查看包含所有示例的代码库:https://github.com/platformatic/ssr-performance-showdown。
确保一致性
我们确保所有示例都具有相同的特征:
在搭载 2020 年款 MacBook Air M1,配备 8GB 内存,macOS Ventura 系统上运行了 Node v22 的测试。
fastify-html
我们先从一个例外开始:fastify-html,这是一个 Fastify 插件,用于包装 ghtml,每秒可以处理 1088 个请求。正如之前提到的,这个设置与其他设置不同,因为它不需要 Vite,因为不需要特殊的语法或转换。
我们在测试中添加了 Fastify-HTML 作为基准。由于它只是对一个简单的 HTML 模板库的封装,没有其他库的高级功能,因此与其他库的比较并不理想。由于其更简单的特性,我们已经预期它是性能更好的库,并希望看看其他功能完备的库落后了多少。
下面是使用的模板代码 —— 请注意,使用了 createHtmlFunction (模仿 @fastify/vite)用于注册一个布局函数,该函数用于渲染文档外壳:
import Fastify from 'fastify'
import fastifyHtml from 'fastify-html'
import { createHtmlFunction } from './client/index.js'
const server = Fastify()
await server.register(fastifyHtml)
server.addLayout(createHtmlFunction(server))
出于参考,我们还添加了一个使用传统 EJS(基于 @fastify/view)的测试。它能够每秒处理 443 个请求。
Vue
位居第二位的是 Vue,每秒可以处理 1028 个请求,如果你想要出色的 SSR 性能并且想要一个真正全面的库生态系统,那么 Vue 可能是最好的选择。
Vue API 用于同步服务器端渲染的是 renderToString()
:
import { renderToString } from 'vue/server-renderer'
// ...
await server.register(FastifyVite, {
async createRenderFunction ({ createApp }) {
return async () => ({
element: await renderToString(createApp())
})
}
})
Svelte
第三名是 Svelte 5(仍然是预发布版本),它每秒能够处理 968 个请求,考虑到其丰富的功能集,这个性能表现相当令人印象深刻。
Svelte 具有自己的非 JSX 模板语法,并且其引擎似乎效率惊人,因此如果您需要一个具有成熟库生态系统且不希望在 SSR 性能上妥协的框架,则它是一个极佳的选择。
用于服务器端渲染的 Svelte API 是 render()
,来自 Svelte 5。
await server.register(FastifyVite, {
root: import.meta.url,
createRenderFunction ({ Page }) {
return () => {
const { body: element } = render(Page)
return { element }
}
}
})
请注意,render()
函数也会返回头部和主体属性。
Solid
排在第四位的是 SolidJS,每秒可处理 907 个请求。它与 Svelte 的差距非常小。Solid 是一个很有前途的替代 React 的选择,但其生态系统仍在发展中。
我们注意到,SolidJS 在其加载过程中确实存在使用 ID 的问题。以下是 Vue 和 Solid 分别生成的标记:
<div class="tile" style="left: 196.42px; top: 581.77px">
<div data-hk=1c2397 class="tile" style="left: 196.42px; top: 581.77px">
这意味着大部分性能开销来自于需要通过网络发送的额外片段。然而,我们仍然想要验证这一点:框架在正常、真实世界情况下的表现,这意味着需要启用诸如数据刷新等客户端功能。
对于模板部分,我们使用了 @fastify/vite 的 createRenderFunction
钩子来捕获 Solid 组件函数( createApp ):
import { renderToString } from 'solid-js/web'
// ...
await server.register(FastifyVite, {
root: import.meta.url,
createRenderFunction ({ createApp }) {
return () => {
return {
element: await renderToString(createApp)
}
}
}
})
Preact
React 的受欢迎的年轻弟弟排在第五位,每秒处理 717 个请求。尽管 Preact 与 React 非常相似,但它具有更快、更轻量级的特性。
用于同步服务器端渲染的 Preact API 是 renderToString()
:
import { renderToString } from 'preact-render-to-string'
// ...
await server.register(FastifyVite, {
root: import.meta.url,
createRenderFunction ({ createApp }) {
return () => {
return {
element: renderToString(createApp())
}
}
}
})
React
React 19 RC 排在第六位,每秒提供 572 次请求。
用于同步服务器端渲染的 React API 是 renderToString()
:
import { renderToString } from 'react-dom/server'
// ...
await server.register(FastifyVite, {
root: import.meta.url,
createRenderFunction ({ createApp }) {
return () => {
return {
element: renderToString(createApp())
}
}
}
})
结束
那么这些结果意味着什么呢?
在上面,我们看到 fastify-html 和 Vue,紧随其后的是 Svelte 和 Solid。Vue 和 Svelte 可能在 SSR 性能和生态系统成熟度之间提供了最佳的权衡。
如前所述,添加了 fastify-html 测试作为基准,并展示了通过去除全功能前端框架并仅使用最小化模板可以提高的性能。
关于本文
译者:@飘飘
作者:@Matteo Collina
原文:https://blog.platformatic.dev/ssr-performance-showdown
这期前端早读课
对你有帮助,帮” 赞 “一下,
期待下一期,帮” 在看” 一下 。