Airtable 如何通过服务器端渲染 React 改进 SEO。搜索网络是新用户发现新业务和解决方案的常用方式。成功的用户获取策略通常涉及寻找方法来增加您网站的流量,排名高于竞争对手,并最终说服用户注册您的产品或安装您的应用程序。小的优化有可能产生巨大的影响,这就是搜索引擎优化 (SEO) 至关重要的原因。
在 2021 年期间,我们着手为我们的营销登陆页面创建一个新的以 SEO 为中心的基础架构,以优化我们的搜索引擎排名并吸引更多 Airtable 的潜在用户。更高的排名意味着来自使用搜索引擎的人的新印象、点击和转化。
从历史上看,Airtable 的登录产品和注销营销登录页面位于同一个 repo 中,主要使用客户端呈现的 React。当我们决定将注销页面拆分到它们自己的存储库中时,我们有机会重新设计登录页面的基础结构,以更好地满足 SEO 需求。
优化 HTML 的生成方式是 SEO 的基础,所有其他改进都将在此基础上进行。换句话说,如果您的 Web 应用程序框架和构建系统不能很好地促进 SEO,那么在其他层面上投资 SEO 工作就会变得更加困难。我们对营销页面的不同基础架构选项进行了探索:
- 静态网络应用
- 客户端呈现的网络应用程序
- 服务器端呈现的网络应用程序
我们最终决定服务器端渲染最好地为 SEO 的成功建立一个代码库;并选择 NextJS 作为框架来促进它。让我向您介绍为什么我们做出这个决定,以及它如何使专注于改进其 SEO 基础架构的团队受益。
项目目标
- 让搜索引擎尽可能容易地索引我们的网页
- 确保对我们页面的更改可以及时编入索引
- 无需重新部署网络应用程序即可启用动态呈现的内容
- 继续利用 React 和 Typescript 来保持两个存储库的一致性
Google 如何抓取网页并将其编入索引
为了在不同的网络应用程序基础设施选项之间进行评估,我们需要了解搜索引擎如何发现和解析网页以产生有机搜索结果。2021 年,谷歌占所有搜索引擎搜索量的 90% 以上。因此,我们的 SEO 评估将几乎完全集中在 Google 搜索上。
更新页面或添加新页面后,新内容可能需要4 天到 4 周的时间才能显示在 Google 搜索结果中。Google 的网络爬虫Googlebot在将页面数据发送到排名算法之前具有三个处理阶段:
- 爬行
- 渲染
- 索引
爬行队列
爬虫负责搜索 Internet 以发现 URL。它向爬行队列中的已知 URL 发送 HTTP 请求以检索页面的 HTML。然后,爬虫会解析 HTML 以查找更多要添加到爬网队列的 URL。
例如,如果从抓取队列中检索到 URL 并返回以下 HTML,则在检查文件以确保允许该页面被索引/store后,将发现该 URL 并将其添加到抓取队列中。robots.txt
<html lang="zh-cn">
<head>
<script src="main.js" />
</head>
<body>
<div>
<h1>Kitty Litter</h1>
<a href="/store">网上商城</a>
</div>
</body>
</html>
爬虫不执行任何 JavaScript,只会解析它提供的 HTML。这意味着如果页面在 JS 执行之前包含所有必要的内容,那么 Googlebot 已经拥有索引和排名页面所需的所有信息。
另一方面,如果 JS 需要运行以生成页面内容,那么 Googlebot 需要先完成渲染网站的额外工作,然后才能正确抓取页面并将其编入索引。
JS 渲染队列
Googlebot 的渲染器将使用无头 Chromium 实例来解析和执行 JS,以生成完整的 HTML 页面。HTML 被发送到爬虫,因此可以再次解析它并可以发现 URL。呈现的 HTML 也被发送到索引器进行处理。
想象一下每天持续抓取和呈现所有互联网需要多少处理能力!甚至谷歌也有其局限性。您的网站被编入索引的速度受Googlebot 实例的可用性、带宽和时间的限制。
但是,与任何代码一样,JS 中可能存在阻止 Googlebot 为页面编制索引的错误。企业需要主动监控Google Search Console,以检查 Googlebot 是否遇到 JS 错误。
索引队列
索引器负责在将页面内容添加到搜索索引之前解析和分析页面内容。在此步骤中,Googlebot 将尝试根据标题、关键字和整个页面内容来理解内容的意图。
在设置初始 Web 应用程序基础结构后,为索引器优化内容成为 SEO 的主要焦点。
比较基础架构选项
下表总结了我们考虑的三个基础架构选项之间的比较以及每个选项的优缺点,我将对此进行更详细的讨论。
静态HTML
静态网站可以说是最容易设置的,因为在最简单的形式中,它由具有固定内容的 HTML 文件组成,这些文件可以用作静态的、可缓存的资产。不需要服务器逻辑,文件完全按照存储的方式发送到浏览器。术语Jamstack有时用于描述此架构,因为部署只是一堆文件。
尽管可以在没有任何 Web 库或框架的情况下构建静态网站站点,但静态站点生成器 (SSG)(例如 Next.js、Hugo、Gatsby、Jekyll 等)允许使用组件等复杂的 Web 开发功能。这些框架在构建时将代码转换为静态 HTML,然后可以将其部署到内容分发网络 (CDN)。在构建期间而不是在 Web 服务器上按需生成标记的过程称为预渲染。
初始 HTML 包含所有内容
相同的 HTML 会在第一页加载时提供给每个访问者,包括搜索引擎机器人。这使得 Googlebot 无需解析和执行 JS 即可轻松抓取页面并将其编入索引。这并不意味着我们不能在页面上使用 JS 来使元素交互,但由于我们没有在客户端使用 JS 来生成 HTML,我们正在为 SEO 的成功做好准备。
无与伦比的速度和性能
因为静态 Web 应用程序项目只是一堆文件,所以它们可以直接从 CDN 分发。没有应用服务器或任何预处理,以及用户浏览器可以缓存静态文件的事实意味着应用程序将具有非常快的性能。快速加载时间意味着更好的用户体验和更好的 SEO 支持。
需要部署才能更改内容
更新页面是指通过代码部署更新文件系统上的一个或多个文件。这对于简单的项目可能没问题,但对于更新非常频繁且没有持续部署 (CD) 的更大更复杂的项目,这可能会成为一个巨大的麻烦。
客户端呈现 (CSR) HTML
客户端呈现的应用程序意味着 HTML 内容几乎完全使用 JS 在浏览器中呈现。页面的初始 GET 请求返回一个部分 HTML 文件,其中包含<script>引用主 JS 文件的标记。JS 代码运行并将页面内容注入浏览器的 DOM。
每个页面都不是有不同的 HTML 文件,而是在浏览器中动态创建每个路由。React、Vue、Angular 和 Ember 都是客户端渲染框架的例子。与静态站点类似,不需要 Web 服务器逻辑,可以将 JS 包和其他构建工件部署到静态服务器或 CDN。
初始 HTML 缺少关键页面内容
如果您要在浏览器中禁用 JS 并访问客户端呈现的网页,该页面很可能会丢失关键的页面内容。<script>这是因为在执行标记中引用的 JS 以将页面内容注入浏览器的 DOM之前,从服务器检索的初始 HTML 是不完整的。
例如,如果下面的 HTML 被抓取工具抓取,它将没有可抓取的内容,Google 需要将 URL 添加到呈现队列。with 元素id=”root”是DOM 容器,页面内容将在 JS 执行后在运行时注入。
<html lang="en">
<head>
<script src="main.js" />
</head>
<body>
<div id="root">
正在加载...
</div>
</body>
</html >
性能影响
由于浏览器正在执行生成 HTML 的繁重工作,因此需要将任何正在使用的第 3 方 JS 依赖项下载到客户端,这会增加带宽并降低性能。浏览器需要做的工作越多,对用户体验和 SEO 的影响就越大。因为 JS 必须在 HTML 被抓取之前运行,所以 CSR 网页需要更长的时间才能出现在搜索结果中。
动态内容
由于 HTML 是在客户端动态生成的,因此可以非常灵活地调用 API 并向不同的用户显示不同的内容,或者通过更新 CMS 或数据库来更新内容而无需部署代码。
服务器端呈现 (SSR) HTML
服务器端呈现是将客户端 JavaScript 应用程序呈现为服务器上的静态 HTML 的过程。SSR 是一个很大的类别,与静态站点和 CSR 都有重叠。它类似于静态站点生成器,因为 JS 框架用于从服务器生成 HTML,但 SSR Web 应用程序可以在 Web 服务器上运行时动态地执行此操作。这意味着当用户或机器人访问网页时,服务器会收到 http 请求并动态生成特定于该请求的 HTML,然后将其返回给客户端。我所说的这种 SSR 的“风味”,有时也被称为经典 SSR。为避免将此基础结构与预渲染混淆,主要区别在于渲染发生在运行时而不是构建时。
所有流行的现代 Web 框架(如 React、Vue 和 Angular)都支持某种形式的 SSR,而 Next.js 等框架专门围绕支持服务器端渲染而构建。
初始 HTML 包含所有内容
由于页面的初始 GET 请求返回 HTML 中的所有内容,因此 Googlebot 可以很容易地抓取页面并将其编入索引。
动态内容
由于 HTML 是在服务器上动态生成的,因此可以非常灵活地调用 Web 服务器内的 API、向不同的用户显示不同的内容,或者无需使用 CMS 或数据库部署代码即可更新内容。
性能影响
由于服务器正在执行生成 HTML 的繁重工作,因此会对性能产生影响。这可以通过添加一些 HTML 缓存来调解,但它不会像静态站点那样快。