客户端渲染

在客户端呈现 (CSR) 中,服务器仅呈现页面的准系统 HTML 容器。
在页面上显示内容所需的逻辑、数据获取、模板和路由由在浏览器/客户端中执行的 JavaScript 代码处理。
CSR 作为一种构建单页应用程序的方法变得流行起来。 它有助于模糊网站和已安装应用程序之间的区别。

为了更好地了解其他模式提供的好处,让我们首先深入了解客户端渲染 (CSR),并找出它在哪些情况下工作得很好以及它的缺点是什么。


CSR - 基本结构

考虑这个使用 React 在页面上显示和更新当前时间的简单示例。

HTML:

<div id="root"></div>

JS:

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
 ReactDOM.render(element,document.getElementById('root'));
}
setInterval(tick, 1000);

HTML 只包含一个根 div 标签。

另一方面,内容显示和更新完全在 JavaScript 中处理。 没有到服务器的往返行程,渲染的 HTML 就地更新。

在这里,时间可以被任何其他实时信息替换,例如从 API 获取的汇率或股票价格,并在不刷新页面或往返服务器的情况下显示。


JavaScript 包(bundles)和性能

随着页面显示图像、显示数据存储中的数据和包括事件处理的复杂性增加,呈现页面所需的 JavaScript 代码的复杂性和大小也将增加。

CSR 产生了大量的 JavaScript 包,从而增加了页面的 FCP 和 TTI。

如上图所示,随着 bundle.js 的大小增加,FCP 和 TTI 被向前推。

这意味着用户将在 FP 和 FCP 之间的整个持续时间内看到一个空白屏幕。


优缺点

使用 React,大部分应用程序逻辑在客户端执行,它通过 API 调用与服务器交互以获取或保存数据。

因此几乎所有的 UI 都是在客户端上生成的。 整个 Web 应用程序在第一个请求时加载。
当用户通过单击链接进行导航时,不会向服务器生成用于呈现页面的新请求。 该代码在客户端上运行以更改视图/数据。

CSR 允许我们拥有一个单页应用程序,该应用程序支持无需页面刷新的导航并提供出色的用户体验。

由于为更改视图而处理的数据有限,因此页面之间的路由通常会更快,从而使 CSR 应用程序看起来更具响应性。

CSR 还允许开发人员实现客户端和服务器代码之间的明确分离。

尽管它提供了出色的交互体验,但此 CSR 仍存在一些缺陷。

  1. SEO 考虑因素:
    大多数网络爬虫可以以直接的方式解释服务器呈现的网站。
    在客户端渲染的情况下,事情会变得稍微复杂一些,因为大负载和大量网络请求(例如 API 响应)可能会导致有意义的内容渲染速度不够快,爬虫无法对其进行索引。
    爬虫可能会理解 JavaScript,但存在局限性。因此,需要一些变通方法来使客户端呈现的网站 SEO 友好。

  2. 性能:
    通过客户端渲染,交互过程中的响应时间大大提高,因为没有到服务器的往返。
    但是,对于浏览器第一次在客户端呈现内容,它们必须等待 JavaScript 首先加载并开始处理。
    因此,用户在初始页面加载之前会遇到一些延迟。
    随着 JS 包的大小变大和/或客户端没有足够的处理能力,这可能会影响用户体验。

  3. 代码可维护性:
    代码的某些元素可能会在不同语言的客户端和服务器 (API) 中重复。
    在其他情况下,可能无法完全分离业务逻辑。这方面的示例可能包括货币和日期字段的验证和格式化逻辑。

  4. 数据获取:
    对于客户端呈现,数据获取通常是事件驱动的。
    该页面最初可以在没有任何数据的情况下加载。
    随后可以使用 API 调用在发生页面加载或按钮点击等事件时获取数据。
    根据数据的大小,这可能会增加应用程序的加载/交互时间。

这些注意事项的重要性可能因应用程序而异。
开发人员通常对寻找 SEO 友好的解决方案感兴趣,这些解决方案可以在不影响交互时间的情况下更快地提供页面。
根据应用要求,分配给不同性能标准的优先级可能不同。
有时,使用客户端渲染并进行一些调整而不是采用完全不同的模式可能就足够了。


提升 CSR 性能

由于 CSR 的性能与 JavaScript 包的大小成反比
我们能做的最好的事情就是构建我们的 JavaScript 代码以获得最佳性能。

以下是可以提供帮助的指针列表。

  1. 按需压缩加载:
    确保为初始页面加载有一个合理紧张的 JavaScript 预算。
    一个小于 100-170KB 的压缩包和 gzip 压缩包是一个很好的起点。
    然后可以在需要功能时按需加载代码

  2. 预加载:
    此技术可用于在页面生命周期的早期预加载页面所需的关键资源。
    关键资源可能包括 JavaScript,可以通过在 HTML 的 <head> 部分中包含以下指令来预加载。

<link rel="preload" as="script" href="critical.js">

这会通知浏览器在页面渲染机制启动之前开始加载 critical.js 文件。
脚本将因此更早可用并且不会阻塞页面渲染机制从而提高性能。

  1. 延迟加载:
    通过延迟加载,可以识别非关键资源并仅在需要时加载这些资源。
    使用这种方法可以改进初始页面加载时间,因为最初加载的资源大小减少了。
    例如,聊天小部件组件通常不会在页面加载时立即需要,可以延迟加载。

  2. 代码拆分:
    为了避免大量的 JavaScript 代码,可以拆分代码包。
    代码拆分受 Webpack 等打包器的支持,可用于创建多个可在运行时动态加载的包。
    代码拆分还能够延迟加载 JavaScript 资源。

  3. 服务工作者的应用程序Shell缓存
    这项技术涉及缓存应用程序外壳Shell,它是支持用户界面的最小 HTML、CSS 和 JavaScript。
    Service Worker 可用于离线缓存应用程序外壳。
    这对于提供本机单页应用程序体验非常有用,其中剩余内容根据需要逐步加载。

通过这些技术,CSR 可以帮助提供更快的单页应用程序体验,并具有不错的 FCP 和 TTI。

接下来,我们将看到在服务器端渲染的另一端可用的内容。


知识点

  • bundles
  • FCP
  • TTI
  • FP
  • FCP
  • rel=“preload” as=“script”