原文地址:https://moz.com/blog/javascript-seo
作者的观点谨代表其个人(催眠这类不太可能事件不算),而且他的观点也并不总会代表 Moz 的观点(译者注:moz 应为 https://moz.com)

了解 Javascript 以及它对于搜索性能的潜在影响是一名现代 SEO(Search Engine Optimization) 专业人员的核心技能。倘若搜索引擎不能爬取一个站点,或者不能解析并理解站点的内容,那么任何内容都不会被索引,该站点也不会进入排名。

对于 SEO 来说,关于 Javascript 最重要的问题是:搜索引擎能否看懂内容并且获得网站体验?如果不能,那我们能够利用什么方案来解决这个问题?


基础部分

什么是 Javascript?

当制作一张现代网页的时候,有三个主要的组件:

  1. HTML – 超文本标记语言(Hypertext Markup Language)作为主干,或者作为网站上内容的组织者。它是网站的结构(如标题,段落,列表元素等等),还定义了静态内容。

  2. CSS – 级联式样表(Cascading Style Sheets)是额外添加在网站上的设计,酷炫华丽的效果,式样。它组成了页面的表现层。

  3. JavaScript – JavaScript 代表了交互能力,并且是一个动态网页的核心组件。

更多关于 网页开发 的内容,以及如何编写基础的 JavaScript.

javacssseo.gif

Javascript 要么以 tag 形式放在 HTML 文件中(比如,内嵌在 HTML 里),要么以引用或链接的方式。现在有很多 Javascript 库和框架,包括 jQuery, AngularJS, ReactJs, EmberJS, 等等。

Javscript 库和框架:

什么是 AJAX?

AJAX,或者叫做 Asynchronous JavaScript and XML, 是一系列的 web 开发技术,它们把 Javascript 和 XML 结合在一起,从而能够允许 web 应用与一个后台服务器通信,但不会干扰当前网页的加载。异步(Asynchronous)意味着当异步脚本正在运行的时候,其它函数或者代码行也能够执行。XML 过去是用来传输数据的最重要的语言,然后,术语 AJAX 现在被用作所有类型数据的传输(包括 JSON;我猜 "AJAJ" 听起来不像 "AJAX"那么舒服[双关语])

一种常见的 AJAX 用法是更新网页的内容或布局,但不用初始化整个页面的刷新。正常来说,当一个页面加载的时候,所有在页面上的资源必须从服务器上请求和抓取,然后在页面上渲染出来。但是,有了 AJAX,只有那些页面间不同的资源需要加载,这能够提升用户体验,就好像他们不用刷新整个页面一样。

你可以把 AJAX 视作是最小服务器请求。一个运行中的 AJAX 的最佳示例就是 Google Maps。它的页面更新的时候不会重新加载整个页面(比如,当用户触发导航的时候,最小服务器请求就被使用以加载(变化的)内容)。

Related image

什么是文档对象模型(DOM)?

作为一句 SEO 专业人员,你需要理解 DOM 是什么,因为这是 Google 用来分析和理解网页的东西。

DOM 就是当你 “检查页面元素”(Inspect Element)的时候所看到的东西。简单来说,你可以把 DOM 当作这样的几个步骤,当接收到 HTML 文件之后,浏览器会采用这几个步骤来渲染页面。

浏览器接收的第一样东西就是 HTML 文件。在那之后,它会开始解析这个 HTML 文件里面的内容并且抓取额外的资源,如图片,CSS,Javascript 文件。

DOM 就是从这些解析后的信息和资源中生成的东西。你可以把它视作一种网页代码的结构化的,有组织的版本。

现在,由于被大家称作动态 HTML 的东西,DOM 一般和最开始的 HTML 文件区别很大。动态 HTML 是一种页面根据用户输入,环境条件(如一天中的时段),和其他变量,利用 HTML, CSS, Javascript 来改变内容的能力。

通过 Javascript 填充标签(tag)的简单例子

HTML source

DOM

什么是无界面浏览?

无界面浏览,简而言之,就是抓取不含 UI 的页面。理解无界面浏览很重要,因为Google, 现在百度也是, 利用无界面浏览以获取对于用户体验和网页内容更好的理解。

PhantomJS and Zombie.js 是脚本化的无界面浏览器,主要用于基于测试目的的自动页面交互,以及渲染基于初始请求的 HTML 静态快照(预渲染)


为什么 Javscript 能够挑战 SEO? (以及如何解决这些问题)

关于你网站上的 Javascript,有三个重要需要考虑:

  1. 网页可爬性(crawlability): 机器人爬取你网站的能力。

  2. 可获取性(obtainability): 机器人获取信息和解析你的内容的能力。

  3. 可感知站点延迟(Perceived site latency): 也就是关键渲染路径(Critical Rendering Path)。

网页可爬性(crawlability)

机器人是否能够找到 URL 并且理解你的站点的架构? 这里有两个重要因素:

  1. 对你的 Javascript 屏蔽搜索引擎 (即使是偶尔一次)

  2. 恰当的内部链接, 而不是利用 Javascript 事件作为 HTML 标签的替代品。

为什么说屏蔽 Javascript 有很大影响?

如果搜索引擎 不被允许爬取 javascript, 它们将不能收到你的网站的所有体验。这意味着搜索引擎将看不到最终用户看到的内容。这会降低你的网站对于搜索引擎的曝光率,而且最终被隐藏起来(如果意图的确是恶意的话)。

Fetch as Google, TechnicalSEO.com 的 robots.txt 以及 Fetch and Render 测试工具都能帮助鉴别那些 Googlebot 被屏蔽的资源

最简单的解决这个问题的方式,是通过把资源访问的权限提供给搜索引擎,来让他们全面了解你的用户体验。

!!! 注意: 和你的开发团队一起决定哪些文件应该/不应该被搜索引擎访问。

内部链接

内部链接应该由 HTML 或 DOM 内的常规 anchor 标签(< a >)实现。或者这么说,DOM(使用这样一个 HTML 标签<a href="www.example.com">) vs. 利用 Javscript 函数浏览网站

注意:不要使用 Javascript 的 onclick 事件作为内部链接的替代。虽然最终的 URL 也许能找到或是被爬取(通过 javascript 代码或者 XML 网站地图),但它们不会被关联到站点的全局导航。=

内部链接对搜索引擎来说是一种很强的信号,它能让搜索引擎考量站点的架构和页面的重要性。事实上,内部链接强到足以(在某些情形下)重写‘SEO 提示’(SEO hints),例如规范化标签。

URL 结构

根据历史经验,基于 javascript 的网站(或称 ‘AJAX 网站’)一直在使用 URL 中的碎片标识符(#)。

  • 不推荐的做法:

    • 单一哈希 (#) – 唯一的#字符(pound sign,井号,译者注)是不可爬取的。它是用来标识锚点链接(anchor link,也就是跳转链接)的。它们是允许你跳转到页面某块内容的链接。URL 的单一哈希之后的任何内容永远不会发送给服务器,并且会导致页面自动滚动到首个含有匹配 ID 的元素(或是首个含有以下信息的名字的元素)。Google recommends 避免了 URL 中‘#’字符的使用。

    • Hashbang (#!) (与 转义片段 URL) – Hashbang URL 是一种用以支持爬虫的 hack 做法(Google 现在想要避免这么做,只有 Bing 支持)。几个月前,Google 和 Bing 开发 了一种复杂的 AJAX 解决方案,在这种方案中,一种含有用户体验的 Hashbang(#!) URL,和另一个为机器人准备的等价体验共存,这种体验是转义片段(escaped-fragments)且基于 HTML 的。后来, Google 放弃了这个想法,偏向于获得真实的用户体验。在转义片段中,这里存在两种体验:

      • 真实的体验(原文 Original Experience,就是原来的未转义 URL,译者注) (也就是 URL 重写[pretty URL]): 这个 URL 要么必须包含一个#! (hashbang) 以表明其中存在一个转义片段(escaped fragment),要么包含一个元元素(meta element),以表明一个转义片段(escaped fragment)存在(<meta name="fragment" content="!">)。

      • 转义片段 (也就是丑陋的 URL, HTML 快照): 这个 URL 用 转义片段代替了hashbang (#!),并且被用作 HTML 快照。它被称作丑陋的 URL 因为它实在太长了而且看上去(从任何的角度说的确也是)像某种 hack 行为。

Image result

  • 推荐做法:

    • pushState History API – PushState 是基于导航的,并且是 History API 的一部分(你可以这样看它:你的 web 浏览历史)。从本质上说,pushState 更新了地址栏的 URL 并且只有页面上需要改变的才会更新。它允许 JS 站点利用 “修正过的(clean)” URL。当需要支持客户端浏览器导航或者组合渲染的时候,pushState 目前由 Google 支持

      • pushState 的一种合适的应用是无限滚动(用户触及到页面新的部分,URL 应该更新)。理想情况下,如果用户刷新了页面,用户应该会被定位到同样的页面位置点。然而他们不用刷新页面,因为当他们向下滚动的时候,页面更新了,同时地址栏里的 URL 也更新了。

      • 例: Google 的 John Mueller,实现了一个搜索引擎友好的无限滚动优秀示例,示例在 这里。他用了 replaceState(),和 pushState 不一样,replaceState 不包含同样的返回按钮的功能。

      • 更多内容请阅读: Mozilla PushState History API Documents

可获得性

我们已经展示了搜索引擎使用无界面浏览来渲染 DOM,以获得对用户体验和页面内容更好的理解。这也就是说,Google 能够处理一些 Javascript,和使用 DOM(而不是 HTML 文件)。

与此同时,在一些情形下,搜索引擎会很难理解 Javascript。没人希望Hulu 的问题发生在他们的站点或是客户站点上。理解机器是如何和你的站内内容交互是很重要的,如果你不确定,那么做一些测试。

假设我们正在讨论一个执行 Javascript 的搜索引擎机器,存在一些很重要的元素来让搜索引擎能够获取内容:

  • 如果某些内容必须由用户通过交互来触发,那么搜索引擎也许看不到它。

    • Google 是一个懒虫。它不会点击,不会滚动,而且它也不会登录。如果所有的用户体验都要求来自用户的操作,我们应该采用一些特别的措施来确保机器能够获得同样的体验。
  • 如果 Javascript 在 Javascript load 事件触发5s后才出现,那么搜索引擎也许看不到它。

    • John Mueller 提到 并没有特定的超时阈值,但是,网站的目标应该是在5s内加载完毕。

    • Screaming Frog tests 展示了5s和渲染内容之间的相关性。

    • 加载事件加5s,是 Google’s PageSpeed Insights,Mobile Friendliness Tool, and Fetch as Google 所使用的(可能是指标准,译者注);查阅 Max Prin’s test timer

  • 如果 Javascript 有报错,那浏览器和搜索引擎都不能通过,并且有可能跳过页面的这些部分,如果全部代码都没执行的话。

如何确保 Google 和其它搜索引擎能获取你的内容

1. 测试

最常见的解决 Javascript 的方案也许是不要做任何事(去冲杯咖啡,然后让 Google 展示它在算法上的天赋)。像搜索者一样把同样体验提供给 Google 的是 Google 的偏好场景/Google’s preferred scenario

在 2014年5月,Google 首先宣布能够“更好地理解 web”(如 Javascript)。行业专家暗示,Google 可能在此之前就已经能够爬取 javascript. iPullRank 团队在 2011 年提供了两份在这方面很好的文章: Googlebot is Chrome 和 How smart are Googlebots?(感谢 Josh 和 Mike)。2015 年,Adam Audette 的 Google can crawl JavaScript and leverages the DOM 证实了这件事。因此,如果你能够在 DOM 里看到你的内容,那很有可能你的内容正在被 Google 解析。

adamaudette - I don't always JavaScript, but when I do, I know google can crawl the dom and dynamically generated HTML

最近,Barry Goralewicz 做了 一个酷炫的实验,这个实验测试了不同的 Javascript 库和框架的组合,通过这个实验,确认了 Google 是如何与页面交互的(比如,是否会索引 URL/内容?GSC 如何交互?等等)。它完全展示了 Google 是能够 Javascript 的各种形式交互的,并且强调某些框架也许更有挑战性。John Mueller 甚至组建了一个 Javascript 搜索群组(就我了解到的信息,它的确很有帮助)

所有的这些研究都令人吃惊,它们帮助 SEO 研究人员理解了什么时候应该考虑到这些,什么时候应该更加前瞻性一些。但是,在你决定什么都不做是对你网站的最佳解决方案之前,我建议积极谨慎一些,先实验一些小块的想法。思考一下:Jim Collin 的著作 Great by Choice 里“先小而大”(bullets, then cannonballs)的哲学:

“子弹是一种经验主义的测试,它的目标是学习那些能够工作并且满足三项准则的东西:一发子弹必须低成本,低风险,不易分散注意力....测试人员(原文 10Xers 含义未知,译者注)使用子弹来从经验上验证什么东西真的会有用。有了那些经验上的验证,之后他们就能把他们的资源集中在发射加农炮上,使他们能够从大注上获得巨大的回报

思考测试,然后检查以下几个问题:

  1. 确保你的内容会出现在 DOM 里。

  2. 先在所有页面的子集上测试,看看 Google 是否能够索引内容。

  3. 手动检查你的内容中的引用。

  4. 向 Google 请求,观察内容是否出现。

  5. 假定向 Google 请求发生在 load 事件前后,或者在 timeout 以前。检查 Google 是否能够看到你的内容,以及在你的 robots.txt 里,检查你是否正在屏蔽 Javascript,这是一个很棒的测试。虽然向 Google 发起请求并不能保证完全正确,但这是一个很好的出发点

  6. Note: 如果你没有在 GSC 里被验证过,试试 Technicalseo.com’s Fetch and Render As Any Bot Tool.

在你测试完所有的这些以后,如果仍然有问题,而且搜索引擎和机器依旧很难索引并获取你的内容的话,该怎么办呢?也许你可能考虑替代的搜索引擎 (DuckDuckGo, Facebook, LinkedIn, 等),或者也许你可能用需要被其他机器解析的元信息,比如 Twitter 的总结卡片(summary cards),或是 Facebook 的开放图形标签(Open Graph tags)。如果这其中任意一项在测试中被确认,或出现了问题,那么 HTML 快照也许是唯一的决定。

2. HTML 快照
什么是 HTML 快照?

HTML 快照是一幅完全渲染的页面(就像你能在 DOM 中看到的),这个页面可以被返回给搜索引擎机器(相像成:一个 DOM 的静态 HTML 版本)

Google 在 2009 年引入了 HTML 快照在 2015 年弃用(但仍然提供支持), 并且在 2016 下半年笨拙地把他们称作 “避免”的元素(an element to “avoid”)。HTML 快照是 Google 的一个较有争议的话题,但他们非常重要,需要好好理解,因为在某些情况下,他们是必要的

如果搜索引擎(或者像 Facebook 那样的网站)不能抓取你的 Javascript,那么你最好返回一个 HTML 快照,而不是根本就不让你的内容被索引和理解。理想情况下,你的网站应该利用服务端上某种形式的用户代理检测,并把 HTML 快照返回给机器。

同时,你必须意识到 Google 渴望获得和用户相同的体验(比如,如果测试结果很糟糕且 JavaScript 搜索群组 无法对你的境况提供支持,那么只把 HTML 快照提供给 Google)

担忧

当你想到使用 HTML 快照的时候,你必须考虑到 Google 已经放弃了这种 AJAX 建议用法。尽管 Google 仍然在技术上支持它,但是 Google 推荐你不要去使用它(HTML 快照)。是的,Google 改变主意了,并且现在希望获得和用户同样的体验。这个方向才有意义,因为它让机器能够获得更忠于用户的体验。

第二个考量的因素和隐匿的风险(cloaking risk)有关。如果 HTML 快照被发现不能呈现页面的体验,它就被认为存在隐匿的风险。直接来源::

“HTML 快照必须包含终端用户所能在浏览器看到的同样内容,如果事实情况不能满足,那么就应被视作隐匿(cloaking)” – Google Developer AJAX Crawling FAQs

益处

尽管有这些担心,HTML 快照仍有强大的优势:

  1. 搜索引擎和爬虫能够理解页面体验的事实

    • 某些类型的 Javascript 也许对于 Google 来说很难抓取(咳咳...Angular(也可以叫做 Angular 2)...咳咳)(Angular 是来自 Google 的前端框架,译者注)
  2. 其它引擎和爬虫(像 Bing 和 Facebook) 将能理解这些体验

    • 在其它搜索引擎中,Bing 没有说过它能爬取和索引 Javascript,对于严重依赖 Javascript 的网站来说,HTML 快照也许是唯一的解决方案。作为惯例,在更进一步之前,多多测试以确认的确是这样的。

"It's not just Google understanding your JavaScript. It's also about the speed." -DOM - "It's not just about Google understanding your Javascript. it's also about your perceived latency." -DOM

网站延迟

当浏览器接收到 HTML 文件并创建了 DOM (虽然会有一些预扫描),大多数资源在他们出现在 HTML 文件的时候就已经加载好了。这意味着如果你的 HTML 文件顶部有一个巨大的文件,浏览器首先会加载那个庞大的文件。

Google 的关键渲染路径(critical rendering path)概念是去加载用户即刻最需要的,这可以被解释成:“尽可能快地把所有顶部内容展示在用户面前的屏幕上”

**关键渲染路径(Critical Rendering Path) - 优化后的渲染会尽可能快地逐步加载

progressive page rendering

但是,如果你有没必要的资源或 Javascript 文件堵塞了页面的加载能力,你会陷入“阻塞渲染的 Javascript”的窘境。也就是说,Javascript 阻塞了页面表现出更快加载的可能(或者称作:感知型延迟)

对阻塞渲染的 Javascript 的解决方案

如果你分析了你的页面速度结果(通过 Page Speed Insights ToolWebPageTest.org, CatchPoint 等等之类的工具),并且确认的确存在阻塞渲染的 Javascript 的问题,这里有三种可能的方案:

  1. 内联(Inline):把 Javascript 加在 HTML 文件里

  2. 异步(Async): 让 Javascript 异步加载(在 HTML 标签里加上 "async" 属性)

  1. 延迟(Defer): 把 Javascript 在 HTML 中的位置往后放

!!! 重要事项: 理解脚本必须按优先顺序排放是很重要的。用来加载顶层内容的脚本一定要放在前面,而且不能延迟。同样,任何引用了其他文件的脚本只能被放在引用文件加载之后。保证和你的开发团队一起仔细确认过没有对用户体验的影响。

阅读: Google 开发者的速度文件


TL;DR - 本文的核心

爬虫和搜索引擎将会尽其所能来爬取、执行以及解释你的 Javascript,但这很难保证。你要确保你的内容是可爬取的、可获得的,而且不会产生网站延迟的障碍,关键是所有可能情况都需要测试。根据这些结果,再来评估可能的解决方案。

感谢: 感谢 Max Prin (@maxxeight) 审阅本文内容,并且分享你的知识、观点和智慧。如果没有你,情况可能大不相同。

          **关于 alexis-sanders —**

Alexis Sanders 是一位 Merkle 的客户经理,Merkle 是一家提供全方位服务的数字营销机构。在 Merkle,她为财富500强客户推动他们的机构性能提供支持。她对于 SEO 中的很多领域都饱含热情,包括:性能分析、语义检索、本地、移动、技术性 SEO,以及开发主要用户体验。在她空闲的时间里,她担任国际演讲会的积极带头人,练习柔道和柔术,也很喜欢艺术。