React 和其他类似的程序库(如 Vue.js)逐渐成为需要复杂开发的大型企业的选择,而更简单的方法(如使用 WordPress 主题)将无法满足这些企业的需求。
尽管如此,因为搜索引擎难以有效地渲染 JavaScript,所以 SEO 们最初并没有采用像 React 这样的程序库,而 HTML 源代码中可用的内容是首选。
然而,谷歌和 React 在如何渲染 JavaScript 的发展上已经简化了复杂性,导致 SEO 不再是使用 React 的障碍。
尽管如此仍然存在一些复杂性,我们将在本指南中进行介绍。
关于这一点,我们将介绍以下内容:
React 是由 Meta(前身为 Facebook)开发用于构建 Web 和移动应用程序的开源 JavaScript 程序库,React 的主要特点是它是具有声明性的、基于组件的,并且可以更轻松地操作 DOM。
理解组件的最简单方法是将它们视为插件,例如 WordPress。它们允许开发人员使用 MUI 或 Tailwind UI 等组件库快速构建设计并向页面添加功能。
如果你想了解为什么开发人员喜欢 React,请从这里开始:
React 实现了一个 App Shell 模型,这意味着绝大多数内容,默认情况下将是客户端渲染 (CSR)。
而 CSR 意味着 HTML 主要包含 React JS 程序库,而不是从来自服务器(HTML 源)初始的 HTTP 响应中发送整个页面的内容。
它还将包含混杂 JSON 数据的其他 JavaScript 或包含 React 组件的 JS 文件链接,可以通过检查 HTML 源代码快速判断网站是否为客户端渲染。透过点击右键并选择“查看源代码”(或 CTRL + U/CMD + U)。
如果在那里看不到很多行 HTML,则该应用程序很可能是客户端渲染。
但是当你通过右键点击并选择“Inspect element”(或 F12/CMD + ⌥ + I)来检查元素时,会看到浏览器生成的 DOM(浏览器在其中渲染了 JavaScript)。
结果是你会看到该网站有很多 HTML:
注意第一个 <div> 上的 appMountPoint ID,通常会在单页应用程序 (SPA)中看到类似的元素,因此像 React 这样的程序库知道应该在哪里注入 HTML。像是 Wappalyzer 这一类的技术检测工具也很擅长检测程序库。
Ahrefs 的网站诊断将服务器发送的原始 HTML 和浏览器中的渲染 HTML 保存起来,从而更容易发现站点是否具有客户端渲染的内容。
更好的是,可以同时搜索原始 HTML 和渲染 HTML,用以了解具体在客户端渲染的内容。在下面的例子中,你可以看到这个网站是在客户端渲染的页面关键内容,比如 <h1> 标签。
使用 React 创建的网站更不同于传统的方法:也就是使用像是 PHP 之类的语言将繁重的渲染内容留在服务器上,也称之为服务器端渲染 (SSR)。
在 SSR 之前,开发人员让它变得更加简单。
他们会创建静态的 HTML 文档,将它们托管在服务器上,然后立即发送。服务器不需要渲染任何东西,而浏览器通常很少进行渲染。
SPA(包括那些使用 React 的)现在正全面回到这种静态方法,他们现在在浏览器请求 URL 之前将 JavaScript 预渲染为 HTML。这种方法称为静态站点生成 (SSG),也称为静态渲染。
在实践中,SSR 和 SSG 是相似的。
主要区别在于,当浏览器请求 URL 时使用 SSR 进行渲染,而在构建时使用 SSG(当开发人员部署新代码或网站管理员更改站点内容时)使用框架预渲染内容。
由于服务器在将内容发送到用户浏览器呈现内容之前,存在额外的延迟,SSR 可以更加动态但会更慢。
因为内容已经被渲染所以 SSG 会更快,这意味着它可以立即提供给用户页面内容(也就意味着更快的 TTFB)。
要了解 React 默认的客户端渲染方法为何会导致 SEO 的问题,首先需要了解 Google 如何抓取、处理和索引页面。
我们可以通过以下步骤总结其工作原理:
- 爬取 – Googlebot 针对抓取队列中的网址向服务器发送 GET 请求并保存响应内容,Googlebot 为 HTML、JS、CSS、图像文件等执行此操作。
- 处理 – 这包含将从 HTML 内的 <a href> 找到的链接 URL 添加到爬网队列中,它还包括在 <link> 标记中找到的排队资源 URL (CSS/JS) 或 <img src> 标记中的图像。如果 Googlebot 在这个阶段发现了一个 noindex 标签,这个过程就会停止,Googlebot 不会渲染内容,Caffeine(谷歌的索引器)也不会索引它。
- 渲染 – Googlebot 使用无头 Chromium 浏览器执行 JavaScript 代码,以查找 DOM 中的其他内容,而不是 HTML 源代码,它对所有 HTML URL 执行此操作。
- 索引 – Caffeine 从 Googlebot 获取信息,对其进行规范化(修复损坏的 HTML)然后尝试理解,预先计算一些排名信号,以便在搜索结果中提供排名。
从历史上看,React 和其他 JS 库的问题是因为 Google 没有很好地处理渲染过程。
一些例子包括:
- 不渲染JavaScript – 这是一个较老的议题了,但谷歌在 2008 年才开始以有限的方式渲染 JavaScript。然而,它仍然依赖于 2009 年创建的 JavaScript 网站的抓取方式。(谷歌已经弃用了该方式。)
- 渲染引擎 (Chromium) 已过时 – 这导致缺乏对最新浏览器和 JavaScript 的功能支持,如果使用了 Googlebot 不支持的 JavaScript 功能,页面可能无法正确呈现,这可能会对你的内容索引产生负面影响。
- Google 出现渲染延迟 – 在某些情况下,这可能意味着最多会延迟数周,从而减慢内容更改后达到索引阶段的时间,这可能会排除那些大多数需要依靠谷歌渲染内容的网站。
值得庆幸的是,谷歌现在已经解决了大部分这些问题。Googlebot 现在是常青状态,这意味着它始终支持 Chromium 的最新功能。
此外现在的渲染延迟为 5 秒,正如 Martin Splitt 在 2019 年 11 月的 Chrome 开发者峰会上宣布的那样:
去年 Tom Greenaway 和我在这个舞台上告诉你,“嗯,你知道,这可能需要一周的时间,我们对此感到非常抱歉。”现在把这个忘记好吗? 因为新的数字看起来好多了。我们实际上检查了这些数字并发现,我们从爬行到实际呈现这些结果之间所花费的时间是在中位数上,是 5 秒!”
这一切听起来都是正向的,但是客户端渲染并让 Googlebot 呈现内容是正确的策略吗?
答案很可能仍然是否定的。
在过去的五年中,谷歌在处理 JavaScript 内容方面进行了创新,但完全由客户端渲染的网站引出了其它需要考虑的问题。
重要的是,你可以克服 React 和 SEO 的所有问题。
React JS 是一个开发工具,React 与开发堆栈中的其他工具并没有什么不同,无论是 WordPress 插件还是你选择的 CDN,如何配置会决定是否会降低/增强 SEO。
归根结底 React 还是有利于 SEO,因为它改善了用户体验,只需要确保考虑以下常见问题。
1. 选择正确的渲染策略
你需要用 React 解决最重要的问题是它如何渲染内容。
如前所述,Google 现在擅长渲染 JavaScript。但不幸的是其他搜索引擎并非如此,Bing 对 JavaScript 渲染有一些支持,不过它的渲染效率仍未知,百度、Yandex 等其他搜索引擎也仅提供有限的支持。
提出这个未知数,能为解决服务器端渲染提供了一个很好的案例,以确保所有爬虫都能看到网站的内容。
此外,在服务器上呈现内容还有另一个重要的好处:加载时间。
加载时间
渲染 JavaScript 占用大量 CPU;这使得像 React 这样的大型程序库加载速度更慢,并对用户来说更具交互性。对于 SPA,尤其是在移动设备这种用户查看页面的主要方式上,通常会看到 Core Web Vitals(例如交互时间 (TTI))要高得多。
但是在浏览器进行初始渲染后,随后的加载时间往往会更快,原因如下:
- 客户端渲染不会让整页刷新,这意味着程序库只需要加载一次。
- React 的“diffing”算法只会改变 DOM 中已更改状态的 HTML——致使浏览器仅重新渲染已更改的内容。
根据每次访问查看的页面数,这可能导致实际数据总体上是正向的。
但是如果网站每次访问浏览的页面数量很少,你就很难获得所有核心网页指标(Core Web Vitals)的正向实际数据。
解决方案
最好的方式就是选择 SSR 或 SSG,主要是因为:
- 更快的初始渲染。
- 不必依赖搜索引擎爬虫来渲染内容。
- 由于浏览器在交互之前解析和渲染的 JavaScript 代码更少,TTI 得到了改进。
透过 ReactDOMServer 可以在 React 中实现 SSR,但是我建议使用 Next.js 的 React 框架并使用其 SSG 和 SSR 选项。你也可以使用 Next.js 实现 CSR,但由于速度关系,该框架让用户更倾向 SSR/SSG。
Next.js 支持它所谓的“自动静态优化”,实际上这意味着可以在站点上拥有一些使用 SSR 的页面(例如帐户页面)和使用 SSG 的其他页面(例如你的博客)。
呈现结果:非动态页面的 SSG 和快速 TTFB,以及 SSR 作为动态内容备份的渲染策略。
既然我们在谈论速度,我如果不提其他优化方式反而是在帮倒忙。Next.js 优化了 React 应用程序的关键渲染路径,具有以下功能:
- 图像优化 – 这增加了 <img> 的宽度和高度属性、srcset、延迟加载和图像大小调整。
- 字体优化 – 这内联了关键字体 CSS 并添加了字体显示控制。
- Script 优化 – 这使你可以选择何时加载脚本:在页面交互或懒加载之前/之后。
- 动态导入 – 如果实施代码拆分的最佳实践,此功能可以在需要时更轻松地导入 JS 代码,而不是让它在初始渲染时加载并减慢它的速度。
速度和正向的 Core Web Vitals 是一个排名因素,尽管是次要因素。Next.js 的功能可以更轻松地创建出色的网页体验,从而带来竞争优势。
许多开发人员使用 Vercel(Next.js 的创建者)部署他们的 Next.js Web 应用程序,它拥有全球边缘服务器网络;这使得加载时间更快速。
Vercel 提供有关平台上部署的所有站点的 Core Web Vitals 的数据,但你也可以使用 Ahrefs 的网站诊断获取每个 URL 的详细网页体验核心指标数据。
只需在项目的爬网设置中添加 API 密钥。
运行审核后,前往查看性能区域。在那里 Ahrefs 的网站诊断将展示显示来自 Chrome 用户体验报告 (CrUX) 和 Lighthouse 的数据的图表。
2. 正确使用状态码
大多数 SPA 的一个常见问题是它们没有正确呈现状态代码,因为服务器没有加载页面,而浏览器有。你通常会看到以下问题:
- 没有 3xx 重定向,而是使用 JavaScript 重定向。
- 4xx 状态代码未报告“未找到”URL。
你可以在下面看到我使用 httpstatus.io 在 React 站点上运行了一个测试,该页面显然应该是 404,但它却返回 200 状态码,这称为软 404。
这里的风险是谷歌可能决定索引该页面(取决于其内容),然后 Google 可以将其提供给用户,或者在评估网站时使用。
此外呈现 404 有助于 SEO 审核网站,如果不小心在内部链接到 404 页面并返回 200 状态代码,那么使用审核工具快速发现该问题可能会变得更困难。
有几种方法可以解决这个问题,如果是客户端渲染:
- 使用 React 路由器框架。
- 创建一个 404 组件,在无法识别路线时显示。
- 将 noindex 标签添加到“未找到”页面。
- 将带有“404:找不到页面”之类的消息使用 <h1>,这并不理想,因为我们沒有报告 404 状态码。但它会阻止谷歌将该页面编入索引,并帮助它将该页面识别为软 404。
- 当需要更改 URL 时使用 JavaScript 重定向。同样的這并不理想,但 Google 确实遵循 JavaScript 重定向并传递排名信号。
如果使用 SSR,Next.js 使用狀態响应帮助器會使这变得简单,它允许你设置所需的任何状态代码,包括 3xx 重定向或 4xx 状态代码。我使用 React Router 概述的方法也可以在使用 Next.js 时使用,但是如果你使用的是 Next.js,那么可能还能夠实现 SSR/SSG。
3. 避免杂凑(hash)URLs
这个问题在 React 中并不常见,但必须避免像下面这样的杂凑 URL:
- https://reactspa.com/#/shop
- https://reactspa.com/#/about
- https://reactspa.com/#/contact
一般来说,谷歌在杂凑之后不会看到任何东西,所有这些页面都会被视为 https://reactspa.com/。
解决方案
带有客户端路由的 SPA 应该布署 History API 来更改页面。
你可以使用 React Router 和 Next.js 能更容易地做到这一点。
4. 在相关的地方使用 <a href> 链接
SPA 的一个常见错误是使用 <div> 或 <button> 来更改 URL,这不是 React 本身的问题,而是程序库的使用方式。
这样做会给搜索引擎带来问题,如前所述当 Google 处理 URL 时,它会在 <a href> 元素中查找要抓取的其他 URL。
如果缺少 <a href> 元素,Google 将不会抓取 URL 也不会传递 PageRank。
解决方案
解决方案是 <a href> 的 URLs 链接到你希望 Google 发现的页面。
检查是否正确链接到 URL 很容易,只要检查内部链接的元素并检查 HTML 以确保已包含 <a href> 链接。
如上例所示,如果不是的话可能会遇到问题。
但重要的是,要了解缺少 <a href> 链接并不总是问题,CSR 的一个好处是,当内容对用户有帮助但对搜索引擎没有帮助时,可以在客户端更改内容并且不包含 <a href> 链接
在上面的示例中,网站使用分面导航链接到数百万个过滤器组合,这些过滤器对搜索引擎抓取或索引并没有用处。
在客户端加载这些筛选器是很有意义的一件事,因为该网站可以透过不添加 <a href> 链结让 Google 来节省抓取预算。
Next.js 通过其链结组件使这变得简单,可以将其配置为允许客户端导航。
如果你决定布署一个完整的 CSR 应用程序,可以使用使用 React Router 的 onClick 和 History API 更改 URL。
5. 避免延迟加载必要的 HTML
当用户点击或悬停在一个元素上时,很常见到使用 React 开发的网站将内容注入 DOM(仅因为使用程序库很容易做到)。
这本身并不坏,但是以这种方式添加到 DOM 的内容是不会被搜索引擎看到,如果注入的内容包括重要的文本内容或内部链接,这可能就会有负面影响:
- 页面表现如何(因为 Google 不会看到内容)。
- 其他 URL 是否能被发现(因为 Google 不会找到内部链接)。
这是我最近审核 React JS 网站上的一个示例,这里我将展示一个著名的电子商务品牌,其分面导航中具有重要的内部链接。
但是当你点击“筛选器”按钮时,会在 DOM 中注入一个显示移动设备导航的模式,查看下面 HTML 中的第二个 <!—-> 可以看到:
解决方案
发现这些问题并不容易,据我所知没有工具会直接告诉你。
相反的,它需要透过检查常见元素来查看,例如:
- 选项卡
- 模式
- 页签
- 下拉菜单
- 汉堡菜单
然后需要检查它们上的元素,并在通过点击或悬停来打开/关闭它们时观察 HTML 发生的情况(就像我在上面的 GIF 中所做的那样)。
假设你注意到 JavaScript 正在向页面添加 HTML,这种情况下需要与开发人员合作。如此一来,不是透过内容注入 DOM 的方式,而是默认包含在 HTML 中,并通过 CSS 使用 visibility: hidden; 或是 display: none; 来显示或隐藏内容。
6.不要忘记基本面
虽然 React 应用程序还有其他 SEO 的考虑因素,但这并不意味着其他基础知识不适用。
仍然需要确保你的 React 应用程序遵循以下最佳实践:
最后的想法
不幸的是使用 React 应用程序,增加了原本技术 SEO 就需要检查的一份很长的问题清单。但是多亏了像 Next.js 这样的框架,它使 SEO 的工作比以往更加简单。
希望本指南能帮助你更好地了解作为 SEO 使用 React 应用程序时需要考虑的其他注意事项。
对使用 React 有任何疑问吗?来 twitter 上找我。
译者,李元魁,SEO 分解茶博客创始人