专栏名称: 前端早读课
我们关注前端,产品体验设计,更关注前端同行的成长。 每天清晨五点早读,四万+同行相伴成长。
目录
相关文章推荐
前端早读课  ·  【早阅】JWT 认证:最佳做法和何时使用 ·  1 周前  
前端早读课  ·  【早阅】JS中的OOPS - 终极指南 ·  1 周前  
前端大全  ·  30+ 个工作中常用到的前端小知识(干货) ·  1 周前  
前端大全  ·  吊打 NVM 的 4 款 Node.js ... ·  1 周前  
前端早读课  ·  在敏捷产品管理中优先考虑用户故事 ·  1 周前  
51好读  ›  专栏  ›  前端早读课

【第3387期】多种前端框架SSR性能大比拼

前端早读课  · 公众号  · 前端  · 2024-10-08 08:00

正文

前言

主要对比了多种前端框架在服务器端渲染(SSR)性能上的表现,并提供了详细的测试结果和分析。今日前端早读课文章由 @飘飘翻译分享。

正文从这开始~~

使用 Node.js 构建高性能 Web 应用时,Server-Side Rendering(SSR)是一个经常被忽视的方面。

【第3134期】从历史的角度探讨多种SSR(Server-side rendering)

在我担任顾问期间,许多项目都围绕着解决 Node.js 的性能问题展开。在这种情况下,罪魁祸首几乎总是 SSR(Server-Side Rendering,服务器端渲染)。SSR 是一种 CPU 密集型活动,很容易成为阻塞 Node.js 事件循环的主要原因。在选择前端框架时,必须考虑到这一点。

我们着手调查当前最受欢迎的库中 SSR 的性能的表现,尤其是那些可以与 Fastify 无缝集成的库。

为了达到这个目的,我们需要生成一个包含大量元素的非平凡样本文档,以便为测试创建一个非常大的页面,从而有更多运行时间来捕获每个库的性能。

因此,我们让一个 LLM 编写了一些代码,用 div 作为 10x10 像素的瓷砖,将螺旋图案绘制到容器中:

 <script>
const wrapper = document.getElementById('wrapper')
const width = 960
const height = 720
const cellSize = 5

function drawSpiral() {
let centerX = width / 2
let centerY = height / 2
let angle = 0
let radius = 0
const step = cellSize

while (radius < Math.min(width, height) / 2) {
let x = centerX + Math.cos(angle) * radius
let y = centerY + Math.sin(angle) * radius

if (x >= 0 && x <= width - cellSize && y >= 0 && y <= height - cellSize)
{
const tile = document.createElement('div')
tile.className = 'tile'
tile.style.left = `${x}px`
tile.style.top = `${y}px`
wrapper.appendChild(tile)
}

angle += 0.2
radius += step * 0.015
}
}
drawSpiral()
script>

随后,我们让它使用我们计划测试的所有库来创建多个版本,并对每个库的渲染引擎进行了适配,而不是依赖原始示例的 DOM 方法。

这是我们的样本文件在包含所有 2398 个 

 元素的示例:

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。

确保一致性

我们确保所有示例都具有相同的特征:

  • 未使用任何客户端响应特性。

  • 所有样式绑定都使用模板字符串进行,除非对于所涉及的框架不适用,例如 React 和 Solid。

  • x 和 y 值使用 toFixed(2) 创建。

  • 除了文档外壳中的那个标签外,不允许使用其他  标签。

在搭载 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

这期前端早读课
对你有帮助,帮” 
 “一下,
期待下一期,帮”
 在看” 一下 。