利用 React 实现 SPA 应用的服务端渲染的技术实现

阅读时长 14 分钟读完

单页应用(SPAs)是现代 Web 应用程序的必要选择,但是由于它们通常需要客户端运行时才能生效,可能会导致性能缺陷、缓慢的初次加载时间,以及 SEO 问题。服务端渲染(SSR)是一项用于解决这些问题的技术,它允许在服务器上渲染应用程序,并返回已经渲染好的 HTML 给客户端,这样对于许多情况,网络传输和托管网站的负担都可以减少。

在本文中,我们将了解如何使用 React 实现单页应用服务端渲染,以便于在优化我们的应用程序的性能时提供更好的 SEO。首先,我们将介绍什么是 React SSR,以及为什么需要它。然后,我们将向您展示如何在现有的 React SPA 应用程序中启用 SSR。最后,我们还将探讨一些添加 SSR 后的故障排除技术。

React SSR 是什么?

服务端渲染是将要渲染到客户端的 HTML 嵌入到 JavaScript 中生成的。反之,客户端渲染是采用 AJAX/JS 如 React 之类在客户端进行渲染。服务端渲染是把浏览器要做的工作放到了服务端执行,这样我们可以通过消除首次加载大量 JavaScript 来减少页面加载时间并提高性能。

在 React 应用程序中,如果未启用服务端渲染,则 React 在客户端渲染。这导致 React App 的初始加载时间很长,因为在加载脚本文件并准备渲染APP之前,客户端需要下载并执行所有所需的 JS 文件。

利用 React SSR 可以减少初始加载时间和首屏渲染时间,以及为搜索引擎优化提供友好的 HTML 片段,但需要维护更复杂的应用程序生命周期。

如何为现有 React SPA 应用程序启用 SSR?

在将现有 React 应用程序转换为用于服务端渲染的应用程序之前,应该了解一些基础知识。React SSR 在服务器端上运行,并将生成的 HTML 发送给客户端。客户端仍然是用 AJAX/JS 如 React 之类执行某些操作。这意味着需要一种方式将服务器与客户端同步以确保应用程序在两端之间保持状态的一致性。

以下是在现有 React SPA 应用程序中启用 SSR 的步骤:

1. 安装必要的库

使用 SSR 的 React 应用程序需要服务器端渲染库。虽然有很多,但我们将使用 Next.js,因为它具有强大的开箱即用功能和自动化路由。

我们将使用以下命令完成安装:

2. 启用服务端渲染

要在现有应用程序中启用服务端渲染,首先需要做的是创建一个与标准 React 应用程序类似的 Main 组件。

这里演示一个简单示例组件:

-- -------------------- ---- -------
-------- ------ -
  ----- ------ -------- - ------------------
  ------ -
    -----
      ---------- ------------
      ------ ------------- -- ------------------------ --
    ------
  --
-
 
------ ------- -----
展开代码

3. 创建主要的应用程序文件

重要的应用程序文件可以是任何类型,但推荐使用 pages/_app.js 文件。这是一个组件,可以将所有页面作为其子组件来渲染。

-- -------------------- ---- -------
------ ----- ---- -------
------ ---- - --------- - ---- ----------
 
----- ----- ------- --- -
 
  ------ -- -
    ----- - ---------- --------- - - ----------
    ------ -
      -----------
        ---------- -------------- --
      ------------
    -
  -
-
 
------ ------- -----
展开代码

4. 配置基本的服务端渲染

要配置用于服务端渲染的基本设置,需要将多个文件组合在一起。这些文件包括一个入口点,一个页面模板和一个 webpack 配置文件。

—— 入口点

创建到应用程序的入口点。这是通过 next.js中的next.config.js`文件完成的。例如:

-- -------------------- ---- -------
----- -------- - --------------------------
 
-------------- - ----------
  -------- -------- - -------- -- -- -
    -- ---------- -
      ----- --------- - ---------------------
      ----- ------------- - ---------------------
      ---------------- - -
        --------- -------- --------- -- -
          -- -------------------------- ------ ----------
          -- ------- ---------------- --- ----------- -
            ------------------------- -------- ---------
          - ---- -
            ----------
          -
        --
        ---------- ---------------- --- ---------- - -- - ---------------
      -
 
      -----------------------------
        ----- ----------
        ---- --------------
      --
    -
 
    ------ ------
  --
--
展开代码

在这个例子中,我们已经创建了一个规则,通过检测是否是服务器作为一个对外暴露的变量,如果不是服务器则直接返回配置文件;如果是服务器,则过滤掉所有的antd样式变量。这样服务器就可以剔除样式文件以缩短在服务器上生成HTML的时间。同时,这段代码还会将所有依赖转换为服务端模块。

—— 页面模板

页面模板基本上是应用程序页面的 HTML 静态文件。这个文件应该放在public/index.html.这份文件可以定义任何您希望在最终应用程序中显示的内容。一般这部分的设置应该和你单页面上的设置类似(这里我们仅简单风格化h1元素)

-- -------------------- ---- -------
--------- -----
------
  ------
    ----- --------------- --
    ----- ---------- ------------------- --
    ----- --------------- ---------------------------- ------------------ --
    ----- ---------------------------- ----------------- --
    ------------- -------------
  -------
  ------
    ---- ------------------
  -------
-------
展开代码

在下一步中,我们将在公共目录中添加此文件的定义。

—— Webpack 配置文件

最后一步是配置 Webpack 文件。这些文件控制了最终的打包结果和项目的输出目标。

在项目根部创建next.config.js文件,下面代码片段就配置了 webpack 的入口点:

其中,Config 对象与现有应用程序中的 webpack 配置文件类似。但是,我们在这里做了一些调整,以便与服务端渲染功能兼容。为了实现这个过程,我们需要向 Webpack 配置添加四个插件。

-- -------------------- ---- -------
----- ---- - ---------------
----- - ------------------- - - --------------------------------
----- -------------- - -
  --- -----
  --- ----
-
----- -------- - ---------------------------
  ------- - --------------------------
  ---------- - -----------------------
----- ----------------- - -------------------------------
----- ------------------- - ---
----- ---------- - -
   -------- -------- -------- -- -
       ----- - -------- - - -------
       -- ----- --- -------- ---- ------ -- ---- ------
       -- ----------- -
         ----------- - -
           --- --------
           ------ --------
           ------ --------
           --------- -------
         --
       -
       ------------------------- - ---------------------
 
       --------------------
           -- ---- ---- --- ------ ----- -- ------------ -- ----- ---------
           --- -------------------
               --------- -
                   - ----- --------------- --- -------------- --
                   - ----- ------------------ --- ----------------- --
               --
           ----
 
       ----- ------ - -
         ----- ----------
         ---- -
           -
             ------- ------------
             -------- -
               -------------- -----
             --
           --
         --
       --
 
       ------------------------- - ------- ------ ------- ------- ------- -------
       ---------------------------------
 
       ------ -------
       -------------------------
         -
           ----- ----------
           ---- -
             -
               ------- -------------
               -------- -
                 -------------- --
                 -------- -
                   ----- ----------------------------------
                   --------------- --------------------------
                 -
               -
             --
             -
               ------- -----------------
               -------- -
                 ------ ----------
                 -------- -
                   -------------------------
                 -
               -
             --
             -
               ------- --------------
               -------- -
                 ------------------ ----
               -
             -
           -
         -
       --
 
       -- ------------------ -
         ----- --------- - ----------------------
         ----- ------------- - ----------------------
         ---------------- - -
           --------- -------- --------- -- -
             -- -------------------------- ------ -----------
             -- ------- ---------------- --- ----------- -
               ------------------------- -------- ----------
             - ---- -
               -----------
             -
           --
           ---------- ---------------- --- ---------- - -- - ---------------
         --
 
         -----------------------------
           ----- ----------
           ---- --------------
         ---
       -
 
       ------ -------
   --
 
   --------- -----
 
   -- -------- --- ----- -- ----- ---------- --- ---- - -------- -------
   ----- ---------- -
     ------ -
       -- --------------------------------
       -- -
       --   ------- ----------------
       --   ------------ -------------------------
       -- --
       ---------------------------------------
     -
   --
   
   -- -----------------------------------------------------
   -- ------------
 --
 
-------------- - ---------
    --------
        ----------------------
    -
--
展开代码

—— 运行 SSR

现在所有的配置都已经配置好,我们可以开始使用 SSR 生成我们的 React 应用程序。只需在终端中键入以下命令就可以运行:

这将构建和启动你的应用程序,所以你就可以通过 http://localhost:3000 访问你的 SSR 应用。

SSR 时的故障排除技巧

如果你在配置 SSR 时遇到问题,以下是一些问题的快速修复列表:

1. Webpack 搜索文件时出现问题

如果 Webpack 在搜索文件时遇到问题,则可能会看到 Node.js 内部调试日志。要解决这个问题,请确保所有 Webpack 配置文件都设置正确。

2. 服务端上的 React App 异常结束

如果你的 React 应用程序在服务器上异常退出,你需要记住以下内容:

避免为空或 undefined

React 组件在服务器上的状态必须正确处理,否则可能会在组件渲染过程中抛出异常。如果您组件中使用了类似food[0]这样是寻找第一个元素的方法,则应该保证 food 非空或undefined。

避免未处理的 Promise 错误

Promise 错误可能会导致服务器异常退出。确保你的 Promise 状态受到正确的问题处理是非常重要的。

避免未处理的 I/O 错误

I/O 错误也可能会导致代码异常退出。

维护代码中的 try-catch 块

对于您正在运行的任何代码,确保用 try-catch 块包裹代码,并正确捕获和处理错误。

3. 警告“在非异步环境中使用异步 API”

在 SSR期间,React 不要使用异步 API。如果您将异步 API 保留在 React 中,请确保它们仅在浏览器环境中运行。

至此,我们介绍了使用 React 实现 SSR 的基础知识。SSR 可以在某些情况下加速 React 应用程序的加载时间和性能,并使 SEO 更加友好。使用本文中介绍的步骤启用 SSR 并使用适当的故障排除技巧,您可以轻松地优化您的 React App 的性能。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c7b9d1cc0f7239cdf9a6b3

纠错
反馈

纠错反馈