对我们的下一本书感兴趣?了解更多关于使用 React 构建大型 JavaScript Web 应用程序

渲染模式

客户端渲染

在客户端渲染 (CSR) 中,只有页面的基本 HTML 容器由服务器渲染。显示页面内容所需的逻辑、数据获取、模板化和路由由在浏览器/客户端执行的 JavaScript 代码处理。CSR 作为构建单页应用程序的一种方法而流行起来。它帮助模糊了网站和已安装应用程序之间的界限。

为了更好地理解其他模式提供的优势,让我们首先深入了解客户端渲染 (CSR),并找出它在哪些情况下运行良好以及它的缺点。


基本结构

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

index.js
index.html
1function tick() {
2 const element = (
3 <div>
4 <h1>Hello, world!</h1>
5 <h2>It is {new Date().toLocaleTimeString()}.</h2>
6 </div>
7 );
8 ReactDOM.render(element, document.getElementById("root"));
9}
10
11setInterval(tick, 1000);

HTML 只包含一个根 <div> 标签。另一方面,内容显示和更新完全在 JavaScript 中处理。没有到服务器的往返,渲染的 HTML 在原地更新。这里时间可以替换为任何其他实时信息,例如从 API 获取的汇率或股票价格,并在不刷新页面或到服务器的往返的情况下显示。


JavaScript 包和性能

随着页面复杂性的增加以显示图像、从数据存储中显示数据并包含事件处理,渲染页面所需的 JavaScript 代码的复杂性和大小也会增加。CSR 导致了大型 JavaScript 包,这增加了页面的 FCP 和 TTI。

rendering

图像来源:https://www.youtube.com/watch?v=k-A2VfuUROg&feature=youtu.be

如上图所示,随着 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 代码以实现最佳性能。以下是一些可能有所帮助的要点。

  • JavaScript 预算:确保您的初始页面加载具有合理严格的 JavaScript 预算。最初的捆绑包大小小于 100-170KB(压缩和 gzip 后)是一个良好的起点。然后可以根据需要按需加载代码。

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

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

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

  • 延迟加载:使用延迟加载,您可以识别非关键资源,并在需要时才加载它们。使用这种方法可以改善初始页面加载时间,因为最初加载的资源大小会减少。例如,聊天窗口小部件组件通常不需要在页面加载时立即使用,可以延迟加载。

  • 代码分割:为了避免大型 JavaScript 代码包,您可以开始分割包。代码分割由像Webpack 这样的捆绑器支持,它可以用于创建可以在运行时动态加载的多个捆绑包。代码分割还允许您延迟加载 JavaScript 资源。

  • 使用 Service Workers 进行应用程序 shell 缓存:此技术涉及缓存应用程序 shell,即为用户界面提供支持的最小 HTML、CSS 和 JavaScript。Service Workers 可用于离线缓存应用程序 shell。这在提供本机单页应用程序体验时很有用,在这种体验中,其余内容会根据需要逐步加载。

使用这些技术,CSR 可以帮助提供更快的单页应用程序体验,并具有良好的 FCP 和 TTI。接下来,我们将了解服务器端渲染的另一端提供了什么。