什么是 React 服务器端渲染?我应该使用它吗?

2025-06-07

什么是 React 服务器端渲染?我应该使用它吗?

正如标题所述,我将尝试介绍这项不再热门的技术的一些优缺点,并帮助刚接触 React SSR 的人更好地理解它。

首先,让我们深入探讨一些术语

SSR?同构?通用?搞什么鬼?

首先,对于一些不了解(就像我最近才知道)的人来说,服务器端渲染没什么特别的。任何普通的静态网站都是服务器端渲染的,服务器接收你的请求并将 HTML 输出到你的浏览器。
我们也有一些模板语言为我们做了一些巧妙的技巧,这些技巧也被认为是服务器端渲染。
但是,当我们谈论 JavaScript 时,服务器端渲染通常指的是前端代码在后端系统上运行时渲染 HTML 的能力。

SPA + SSR = 同构*

* 或通用

同构或通用应用是可以互换的短语,通常指一种编写应用的方式,以便在服务器端和客户端使用相同的语言。更具体地说,对于 JavaScript 来说,最好的情况是使用相同的语法。
例如,如果您使用 NodeJS 运行后端,则可能正在使用 CommonJS 模块语法。

//...Our awesome app code...
const circle = require('./circle.js');
//...Rest of our awesome app code...
Enter fullscreen mode Exit fullscreen mode

用 ES6 编写 React

//...Our awesome app code...
import React, { Component } from 'react';
//...Rest of our awesome app code...
Enter fullscreen mode Exit fullscreen mode

使用 Webpack,我们可以在应用程序的服务器端开始使用 ES6 导入语法,这是同构应用程序的真正目标。

为什么我首先要使用带有服务器端渲染的 React?

好吧,我们的传统 React 应用程序在加载时会有这样的流程:

  • 浏览器请求页面
  • 暂停
  • 我们得到了一个空的 HTML 和一个指向 JS 文件的脚本标签,所有代码都存放在这个文件中
  • 浏览器请求该脚本
  • 暂停
  • 屏幕上可见的内容

现在我们看到我们与服务器之间有两次往返,这还算可以接受。但假设我们的应用有一个博客文章列表,或者一系列图片,或者其他任何需要通过 API 请求的内容,那么流程就更贴近实际了,看起来就像这样:

  • 浏览器请求页面
  • 暂停
  • 浏览器请求我们的 JS
  • 暂停
  • React 应用启动,从后端请求数据
  • 暂停
  • 屏幕上可见的内容

正如您所看到的,请求数量增加了,因此在用户在屏幕上看到任何内容之前会发生更多的事情。

现在来看看服务器端渲染的 React 应用

  • 浏览器请求页面
  • 暂停
  • 屏幕上可见的内容!

什么?怎么做?让我们更详细地看看

  • 浏览器请求页面
  • 服务器在内存中加载 React
  • 服务器获取所需数据
  • 服务器渲染 React 应用
  • 服务器将生成的 HTML 发送到浏览器
  • 用户看到的内容
  • 需要 JS 文件
  • React App 启动,从后端请求数据
  • 应用程序在屏幕上重新呈现(水合)。

如你所见,在为用户获取一些内容之前,我们只访问了服务器一次。现在,我们在重新渲染所有内容之前提供的内容是静态的,所以如果用户速度非常快,并且在 hydrate 发生之前就开始点击,应用程序将无法响应。

我们用这种方法解决了什么问题?

其中最大的两个是SEO感知性能提升

如果你的应用规模稍大一些,搜索引擎爬虫会将你的页面视为一个几乎空的 HTML,其中只有一个script请求你庞大的 React 应用的标签,因为它不会等到填满 DOM 后再加载,所以你的页面不会被索引。
与此同时,谷歌改进了他们的爬虫,使其能够搜索 JavaScript 创建的内容,但必应或百度仍然缺乏此功能,因此,如果你的大部分受众来自其他搜索引擎,你就必须解决这个问题。

使用 React SSR,你的首次有效绘制时间(在大多数情况下)将显著缩短。这对于一些公司来说是一个重要的指标。你肯定听说过许多公司通过缩短 Web 应用的加载时间来提高利润的故事。( https://wpostats.com/ )

上面我提到了可感知的性能提升,虽然与使用传统 React 应用相比,你确实可以更快地将内容呈现给用户,但问题在于这可能并非性能提升。在稍上方的 SSR 请求示例中,你会看到服务器也在执行客户端执行的所有操作:启动 React、渲染应用并输出 HTML。这意味着你把所有操作都重复了两次,这显然不太理想。此外,renderToString()React 用于将你漂亮的 jsx 代码转换为 HTML 的方法非常慢,而且是同步的。这会给服务器带来更大的负载,导致服务器的初始响应延迟到达。

如果您决定使用服务器端渲染,则可能需要两台服务器:一台用于 API 和业务逻辑,另一台用于渲染。了解渲染过程的任务规模后,您可以扩展渲染服务器以适应增加的负载。

由于我不是第一个遇到这些问题的人,沃尔玛实验室的工程师们创建了一个名为 Electrode 的工具来优化 React SSR 的这些怪癖。他们还写了几篇很棒的文章,如果你读到这里,真的值得一读 :) ( https://medium.com/walmartlabs/using-electrode-to-improve-react-server-side-render-performance-by-up-to-70-e43f9494eb8b )。
此外,还有一些针对 React SSR 的“框架”,例如 Next.js,正在获得社区的广泛关注和支持。

使用 React SSR 还会增加多层级的复杂性。还记得自由使用windowdocument来做事吗?忘了它吧!

我当然只是开玩笑,但你必须格外小心,因为应用程序首先会在 Node 环境中运行,windowdocument例如 和 之类的函数并没有在 Node 环境中定义,所以你必须克制自己不要在 Node 之外使用它们componentDidMountif (typeof window !== 'undefined')我已经记不清我的应用程序崩溃了多少次,直到我习惯了它。

你的 Node 服务器会捕获你的路由,并将其传递给 React 来决定渲染什么,那么它如何访问服务器上的路由器呢?它无法访问。解决方案?双重路由。你的应用程序依赖于 Redux 存储中的某些内容进行渲染?双重存储。

SSR 带来了许多复杂性,幸运的是,像 Next.js 这样的工具解决了其中的许多问题,但如果你坚持自己解决所有这些问题,那将会非常困难。

我应该使用 React 服务器端渲染吗?

或许。

如果您/您的公司确实重视 SEO,并且大量访问来自谷歌以外的搜索引擎,那么是的。

如果您/您的公司确实重视用户感知的性能,请考虑一下,如果您的客户端应用程序性能无法变得更好,那么是的。

在任何其他情况下,我的建议是不要参与其中,它只会增加项目的复杂性而没有太多好处。

文章来源:https://dev.to/mladenstojanovic/what-is-react-server-side-rendering-and-should-i-use-it-5b7i
PREV
5 个让 JavaScript 代码更简洁的小妙招🧹
NEXT
🎙️我创建了“GitPodcast”来帮助开发人员轻松理解💡任何 GitHub 仓库