Web 应用程序的客户端与服务器端与预渲染
已发表: 2022-03-11最近前端社区发生了一些事情。 由于 React 及其内置的服务器端水合功能,服务器端渲染越来越受到关注。 但这并不是以超快的首字节时间 (TTFB) 得分为用户提供快速体验的唯一解决方案:预渲染也是一个非常好的策略。 这些解决方案与完全客户端呈现的应用程序有什么区别?
客户端呈现的应用程序
由于存在 Angular、Ember.js 和 Backbone 等框架,前端开发人员倾向于在客户端渲染所有内容。 多亏了 Google 及其“读取”JavaScript 的能力,它运行良好,甚至对 SEO 也很友好。
使用客户端渲染解决方案,您将请求重定向到单个 HTML 文件,服务器将在没有任何内容(或带有加载屏幕)的情况下交付它,直到您获取所有 JavaScript 并让浏览器在渲染内容之前编译所有内容。
在良好且可靠的互联网连接下,它非常快且运行良好。 但它可能会好很多,而且做到这一点并不难。 这就是我们将在以下部分中看到的内容。
服务器端渲染 (SSR)
SSR 解决方案是我们多年前经常做的事情,但往往忘记了支持客户端渲染解决方案。
使用旧的服务器端渲染解决方案,您构建了一个网页(例如使用 PHP),服务器编译所有内容,包含数据,并将完全填充的 HTML 页面交付给客户端。 它快速有效。
但是……每次你导航到另一条路线时,服务器都必须重新做一遍工作:获取 PHP 文件,编译它,然后交付 HTML,所有的 CSS 和 JS 将页面加载延迟到几百毫秒或甚至整秒钟。
如果您可以使用 SSR 解决方案进行第一个页面加载,然后使用框架通过 AJAX 进行动态路由,只获取必要的数据会怎样?
这就是为什么 SSR 在社区中越来越受关注的原因,因为 React 通过一个易于使用的解决方案普及了这个问题: RenderToString
方法。
这种新型 Web 应用程序称为通用应用程序或同构应用程序。 这些术语的确切含义以及它们之间的关系仍然存在一些争议,但许多人可以互换使用它们。
无论如何,该解决方案的优势在于能够使用相同的代码开发应用程序服务器端和客户端,并通过自定义数据为用户提供真正快速的体验。 缺点是需要运行服务器。
SSR 用于获取数据并使用自定义内容预填充页面,利用服务器的可靠互联网连接。 也就是说,服务器自己的互联网连接比使用 lie-fi 的用户更好),因此它能够在将数据交付给用户之前预取和合并数据。
使用预先填充的数据,使用 SSR 应用程序还可以解决客户端呈现的应用程序在社交共享和 OpenGraph 系统方面存在的问题。 例如,如果您只有一个index.html
文件要交付给客户端,那么它们将只有一种类型的元数据——很可能是您的主页元数据。 当您想要共享不同的路线时,这不会被上下文化,因此您的任何路线都不会显示在其他网站上,其中包含用户想要与世界共享的适当用户内容(描述和预览图片)。
预渲染
通用应用程序的强制服务器对某些人来说可能是一种威慑,对于小型应用程序来说可能是过度杀伤力。 这就是为什么预渲染可以成为一个非常好的选择。
我使用 Preact 和它自己的 CLI 发现了这个解决方案,它允许您编译所有预先选择的路由,以便您可以将完全填充的 HTML 文件存储到静态服务器。 借助 Preact/React 水合功能,您无需使用 Node.js,即可为用户提供超快速的体验。
问题是,因为这不是 SSR,所以此时您没有要显示的用户特定数据——它只是在第一个请求时直接发送的静态(并且有些通用)文件,原样。 因此,如果您有特定于用户的数据,您可以在这里集成一个设计精美的骨架,向用户展示他们的数据即将到来,以避免他们感到沮丧:
还有另一个问题:为了使这种技术发挥作用,您仍然需要有一个代理或其他东西来将用户重定向到正确的文件。
为什么?
对于单页应用程序,您需要将所有请求重定向到根文件,然后框架使用其内置的路由系统重定向用户。 所以第一个页面加载总是相同的根文件。
为了使预渲染解决方案起作用,您需要告诉您的代理某些路由需要特定文件,而不总是需要根index.html
文件。
例如,假设您有四个路线( /
、 /about
、 /jobs
和blog
)并且它们都有不同的布局。 您需要四个不同的 HTML 文件将骨架交付给用户,然后让 React/Preact/etc. 用数据重新水化它。 因此,如果您将所有这些路由重定向到根index.html
文件,则页面在加载过程中会有一种令人不快的、有故障的感觉,因此用户将看到错误页面的骨架,直到它完成加载并替换布局。 例如,用户可能会看到只有一列的主页骨架,而他们要求使用类似 Pinterest 的画廊的不同页面。

解决方案是告诉您的代理这四个路由中的每一个都需要一个特定的文件:
-
https://my-website.com
→ 重定向到根index.html
文件 https://my-website.com/about
→ 重定向到/about/index.html
文件https://my-website.com/jobs
→ 重定向到/jobs/index.html
文件https://my-website.com/blog
→ 重定向到/blog/index.html
文件
这就是为什么这个解决方案对小型应用程序很有用的原因——你可以看到如果你有几百页会有多痛苦。
严格来说,这样做并不是强制性的——你可以直接使用静态文件。 例如, https://my-website.com/about/
无需任何重定向即可工作,因为它会自动在其目录中搜索index.html
。 但是,如果您有参数 url,则需要此代理 — https://my-website.com/profile/guillaume
需要使用自己的布局将请求重定向到/profile/index.html
,因为profile/guillaume/index.html
不存在,会触发 404 错误。
简而言之,上面描述的渲染策略包含三个基本视图:加载屏幕、骨架和最终渲染后的整个页面。
根据策略,有时我们会使用所有这三个视图,有时我们会直接跳转到完全渲染的页面。 只有在一个用例中,我们才被迫使用不同的方法:
方法 | 着陆(例如/ ) | 静态(例如/about ) | 固定动态(例如/news ) | 参数化动态(例如/users/:user-id ) |
---|---|---|---|---|
客户端渲染 | 正在加载 → 已满 | 正在加载 → 已满 | 加载→骨架→完整 | 加载→骨架→完整 |
预渲染 | 满的 | 满的 | 骨架→全 | HTTP 404(找不到页面) |
使用代理预渲染 | 满的 | 满的 | 骨架→全 | 骨架→全 |
固态继电器 | 满的 | 满的 | 满的 | 满的 |
仅客户端渲染通常是不够的
客户端渲染的应用程序是我们现在应该避免的,因为我们可以为用户做得更好。 在这种情况下,做得更好就像预渲染解决方案一样简单。 这绝对是对仅客户端渲染的改进,并且比完全服务器端渲染的应用程序更容易实现。
如果您有一个包含许多不同页面的大型应用程序,那么 SSR/通用应用程序会非常强大。 在与社交爬虫交谈时,它可以让您的内容集中且相关。 搜索引擎机器人也是如此,现在它们在对您的网站进行排名时会考虑您的网站的性能。
请继续关注后续教程,我将介绍如何将 SPA 转换为预渲染和 SSR 版本,并比较它们的性能。