pushState和SEO


80

许多人一直在说,使用pushState而不是hashbang。

我不明白的是,如果不使用hashbang,您将如何对搜索引擎友好?

大概您的pushState内容是由客户端JavaScript代码生成的。

因此,场景是:

我在example.com。我的用户单击一个链接:href="example.com/blog"

pushState捕获点击,更新URL,从某处获取JSON文件,并在内容区域中创建博客文章列表。

通过hashbangs,Google知道转到escaped_fragment URL以获得其静态内容。

使用pushState,Google看不到任何东西,因为它无法使用JavaScript代码加载JSON并随后创建模板。

我看到的唯一方法是在服务器端渲染模板,但这完全抵消了将应用程序层推送到客户端的好处。

那么,我是否正确,pushState根本不适合客户端应用程序进行SEO友好?


将来的读者注意:这个问题已经过时了阅读Google的官方声明-简而言之,现在googlebot支持JS。
mik01aj

Answers:


17

如果使用Google为那些不希望其网址中出现哈希爆炸的人建议的meta标签,该怎么办: <meta name="fragment" content="!">

请参阅此处以获取更多信息:https : //developers.google.com/webmasters/ajax-crawling/docs/getting-started

不幸的是,我认为Nicole并没有澄清我认为OP所存在的问题。问题很简单,如果不使用哈希爆炸,我们将不知道向谁提供内容。Pushstate不能为我们解决这个问题。我们不希望搜索引擎告诉最终用户导航到一些会吐出未格式化JSON的URL。取而代之的是,我们创建URL(触发对更多URL的其他调用),这些URL通过AJAX检索数据并将其以我们喜欢的方式呈现给用户。如果用户不是人类,那么我们可以提供html快照作为替代,以便搜索引擎可以正确地将人类用户定向到他们期望在URL上找到的网址(并以可呈现的方式)。但是最终的挑战是我们如何确定用户类型?是的,我们可以使用。htaccess或用于重写我们检测到的搜索引擎机器人的URL的工具,但我不确定这是多么全面和可靠。Google可能还会因为这样做而对人进行惩罚,但我尚未对其进行全面研究。因此,(pushstate + google的meta标记)组合似乎是一种可能的解决方案。


3
@NickC,好的,我知道了,所以现在我认为一个更好的解决方案是最初显示内容而不包含任何JS。但是在JS的顶部(页面加载完毕并准备好dom后)立即运行了一些代码,以隐藏最初显示的HTML内容或将其替换为JS增强功能。例如,我使用jquery datagrids,所以我将首先显示HTML表,然后立即加载JS以将显示的普通表格数据转换/隐藏/替换为JS网格版本。从那时起,任何其他ajax请求都可以作为JSON与通过pushstate更新的URL配对。
prograhammer 2012年

您对所建议解决方案的经验如何?Google是否索引了此“临时” HTML?它是否可以正确显示在相关的Google搜索中?难道不是因为JS生成的html对初始HTML页面进行了“刷新”,所以这种体验有点“紧张”吗?
Nilesh Kale 2014年

@NileshKale这是我研究的解决方案,它可以很好地完成工作:stackoverflow.com/questions/22824991/…。我只传递了一个HTML表,还传递了一个JSON等效的jqgrid(与HTML中的内容相同)。SEO读取HTML,然后用户通过ajax获得升级的体验以及所有后续请求。使用pushstate,我可以根据用户对网格进行排序/分页的方式来更新URL(不需要hashbang)。这使用户可以保存URL并返回相同的结果。
prograhammer 2014年

我将在几天后尝试对我的答案进行编辑以更好地解释。
prograhammer 2014年

1
现在不建议使用AJAX搜寻方案:developers.google.com/webmasters/ajax-crawling/docs/…。建议更改使用它的网站:plus.google.com/+JohnMueller/posts/LT4fU7kFB8W
保护者

97

pushState如果您需要搜索引擎来阅读内容,那是不好的吗?

不,讨论的重点pushState是完成与hashbang相同的一般过程,但URL看起来更好。想一想当您使用hashbang时会发生什么...

你说:

借助hashbang,Google知道可以转到escaped_fragment URL来获取其静态内容。

换句话说,

  1. Google看到一个链接 example.com/#!/blog
  2. Google要求 example.com/?_escaped_fragment_=/blog
  3. 返回用户应该看到的内容的快照

如您所见,它已经依赖于服务器。 如果您没有从服务器提供内容的快照,那么您的站点将无法正确索引。

那么Google如何用pushState看到任何东西?

使用pushState,google看不到任何内容,因为它无法使用javascript加载json并随后创建模板。

实际上,Google会在上显示其可以请求的任何内容site.com/blog。URL仍然指向服务器上的资源,并且客户端仍然遵守此合同。当然,对于现代客户而言,JavaScript开辟了无需重新刷新页面即可检索内容并与之交互的新可能性,但是合同是相同的。

因此,的预期的优雅之处pushState在于,它为所有新老用户(不支持JS)提供相同的内容,但是新用户获得了增强的体验

您如何让Google查看您的内容?

  1. Facebook方法–site.com/blog在您推/blog送到该状态时,在客户端应用程序将转换成的URL上提供相同的内容。(Facebook还不使用pushState我所知道的,但是他们通过hashbangs来实现)

  2. Twitter方法-将所有传入的URL重定向到等效的hashbang。换句话说,指向“ / blog”的链接会推/blog送到该状态。但是,如果直接提出要求,浏览器将以结束#!/blog。(对于Googlebot,这将按需要路由到_escaped_fragment_。对于其他客户端,您可以pushState返回到漂亮的URL)。

那么,您失去了这种_escaped_fragment_能力pushState吗?

在几个不同的评论中,您说

转义的片段是完全不同的。您可以提供纯净的非主题内容,缓存的内容,而不必承受普通页面的负担。

对于Google来说,理想的解决方案是要么执行JavaScript网站,要么实施某种方式来知道即使对于pushstate网站(robots.txt?)也存在转义的片段URL。

您提到的好处不是孤立的_escaped_fragment_。它为您进行重写并使用特殊命名的GET参数确实是实现细节。没有什么真正的特别之处,您无法使用标准URL进行处理-换句话说,/blog可以/?content=/blog使用mod_rewrite或服务器等效的内容自行重写。

如果您根本不提供服务器端内容怎么办?

如果您不能重写URL并在(或您推送到浏览器的任何状态)提供某种内容/blog,那么服务器实际上不再遵守HTTP协议。

这很重要,因为页面重新加载(无论出于何种原因)都会在此URL提取内容。(请参阅https://wiki.mozilla.org/Firefox_3.6/PushState_Security_Review- “如果推送了新的URI,则视图源和重载都将获取内容。”)

并不是在客户端一次绘制用户界面并通过JS API加载内容是一个坏目标,这并不是因为它实际上并未使用HTTP和URL进行说明,而且基本上也不向后兼容。

目前,这正是hashbang的目的-表示在客户端而非服务器上导航的不同页面状态。例如,重新加载将加载相同的资源,该资源随后可以读取,解析和处理哈希值。

碰巧的是,它们也已被使用(尤其是Facebook和Twitter),以将历史记录更改为服务器端位置,而无需刷新页面。 人们建议在这些用例中为pushState放弃hashbang。

如果在客户端呈现所有内容,则应将其pushState视为更方便的历史记录API的一部分,而不是摆脱使用hashbang的方法。


3
@哈里-你读完我剩下的答案了吗?URL是URL-表示资源定位符。服务器是否相信内容存在于site.com/blog?如果不是,则搜索引擎不存在。的目的pushState不是解决该问题。为了方便。Hashbangs也不解决此问题,这_escaped_fragment_是一个复杂的解决方法,它仍然依赖于服务器具有JS生成内容的快照(如您所说的,由普通用户看到)。 pushState实际上简化了所有这一切。
妮可

1
@Harry-在URL被设计为提供客户端内容之前,它们仍然引用服务器上的资源,并且客户端将以这种方式对待它们,包括bot。这并不意味着您在客户端上尽可能多地执行目标是无效的,但是暂时可能必须使用(丑陋的)哈希爆炸来实现。我已经为您的用例更新了答案。
妮可(Nicole)

1
@哈里首先,我只是说说谷歌为他们所做的事情_escaped_fragment_,我不知道你具体做什么。但是从Google的说法来看,我认为当您看到该查询参数时,您必须在服务器上提供某种内容。在您的情况下,这将需要一些技巧,但是您可以提供一些<noscript>内容或其他内容/blog,然后让JS构建所需的页面。或者,您可以尝试检测机器人并故意提供完全不同的内容。
妮可(Nicole)

2
再一次,正确和最佳答案没有被视为正确……不好,很糟糕。

1
如果我有一个类似这样的链接<a href="product/productName" onclick="showProduct(product)">A product</a>,并且onclick以“ preventDefault()”开头,则AJAXly将有关产品的新内容加载到页面中,并且确保链接“ ... / product / productName”将加载一个版本。在服务器的响应中将包含特定产品内容的页面---因此,该站点仍然可以动态工作,但是通过直接转到产品链接可以正确获得静态内容吗?不需要以这种方式进行pushState或hashbang,不是吗?
Yuval A. 2014年

1

关于pushState和的所有有趣的讨论#!,我仍然看不到pushState如何替换原始海报要求的#!的目的。

当然,我们使99%基于JavaScript的Ajax网站/应用程序SEOable的解决方案正在使用#!。由于客户端渲染是通过HTML,JavaScript和PHP完成的,因此我们在页面登陆控制的加载程序中使用以下逻辑。HTML文件与JavaScript和PHP完全分开,因为我们希望两者都使用相同的HTML(大部分情况下)。JavaScript和PHP基本上是同一件事,但是PHP代码不那么复杂,因为JavaScript具有更丰富的用户体验。

JavaScript使用jQuery将所需的内容注入HTML。PHP使用PHPQuery将所需的内容注入HTML-使用“几乎”相同的逻辑,但比PHP版本简单得多,它将仅用于显示具有SEOable链接的SEOable版本,而不会像JavaScript版本那样进行交互。

所有这些都是构成页面的三个组件,page.htm,page.js和page.php对于使用转义的片段来知道是否要加载PHP版本来代替JavaScript版本的任何内容而言都是存在的。非SEOable内容(例如,只有在用户登录后才能看到的页面)不需要存在PHP版本。一切都很简单。

我仍然感到困惑的是,一些前端开发人员如何不使用服务器端技术与浏览器技术而开发大型站点(凭借Google Docs的丰富性)……如果甚至未启用JavaScript,那么我们的99%JavaScript解决方案如果没有适当的PHP,当然不会做任何事情。

如果启用了JavaScript,可能有一个不错的URL可以登陆PHP服务页面并重定向到JavaScript版本,但是从用户的角度来看,这并不是很好,因为用户是更重要的受众。

附带说明。如果您只是制作一个无需任何JavaScript即可运行的简单网站,那么如果您希望逐步将用户体验从简单的静态呈现内容逐步改善为更好的东西,但是如果您想为用户提供从旅途中获得最佳体验...假设您使用JavaScript或Google Docs之类的工具编写了最新游戏,那么该解决方案的使用就受到限制,因为与用户的愿景相比,优雅地回退只能走得很远该网站。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.