使用pushState
启用的页面,通常使用escaped_fragment
约定重定向SEO机器人。您可以详细了解 here 。
该约定假设您将在单个页面应用程序上的所有URI之前使用(#!
)hashbang前缀。 SEO机器人会在发出页面请求时用它自己的可识别约定escaped_fragment
替换hashbang来逃避这些片段。
//Your page
http://example.com/#!home
//Requested by bots as
http://example.com/?_escaped_fragment=home
这允许站点管理员检测机器人,并将它们重定向到缓存的预渲染页面。
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$ https://s3.amazonaws.com/mybucket/$1 [P,QSA,L]
问题在于,随着广泛适应的pushState
支持,hashbang正在逐步淘汰。它也非常丑陋,对用户来说不是很直观。
那么如果我们使用HTML5模式,其中pushState引导整个用户应用程序呢?
//Your index is using pushState
http://example.com/
//Your category is using pushState (not a folder)
http://example.com/category
//Your category/subcategory is using pushState
http://example.com/category/subcategory
可以使用这个较新的约定重写规则引导机器人到您的缓存版本吗? Related but only accounts for index edge case. Google还 has an article ,建议在{{1}中使用<meta name="fragment" content="!">
对此单边案例使用 opt-in 方法页面的。同样,这是针对单边案例的。在这里,我们讨论的是将每个页面作为 opt-in senario处理。
<head>
我认为http://example.com/?escaped_fragment=
http://example.com/category?escaped_fragment=
http://example.com/category/subcategory?escaped_fragment=
仍然可以用作SEO机器人的标识符,并且我可以提取域和此标识符之间的所有内容,以附加到我的存储桶位置,如:
escaped_fragment
处理此问题的最佳方法是什么?
答案 0 :(得分:1)
在单页网页应用上遇到类似的问题。
我发现这个问题的唯一解决方案是有效地创建页面的静态版本,目的是让谷歌(和其他)机器人可以导航。
你可以自己做,但也有一些服务可以做到这一点并为你创建静态缓存(并通过他们的CDN向机器人提供快照)。
我最终使用了SEO4Ajax,虽然其他类似的服务可用!
答案 1 :(得分:0)
我遇到了完全相同的问题。现在,我已经像这样修改了.htaccess:
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^$ /snapshots/index.html? [L,NC]
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule ^(.*)$ /snapshots/$1.html? [L,NC]
不确定是否有更好的解决方案,但到目前为止它对我有用。 请确保快照的目录结构与网址结构匹配。
答案 2 :(得分:0)
我正在使用Symfony2,虽然其他开发人员告诉我们Googlebot和Bingbot能够很好地执行Javascript以生成自己的HTML代码段,但我并不自信。我也觉得服务静态资源对于运行JS关闭的ppl来说是一个更好的选择(但不太可能),因此无论如何都对提供HTML片段感兴趣,只要它不麻烦。以下是我想要使用但尚未尝试的方法:
以下是其他类似的问题(一个是我的)。
Angularjs vs SEO vs pushState
HTML snippets for AngularJS app that uses pushState?
这是我在该问题中发布的解决方案,我正在考虑自己,以防我想向机器人发送HTML代码段。这将是 Symfony2后端的解决方案:
在Symfony2路由文件中,创建一个与您的SPA匹配的路由。我在localhost.com/ng-test/上运行了一个测试SPA,所以我的路线看起来像这样:
# Adding a trailing / to this route breaks it. Not sure why.
# This is also not formatting correctly in StackOverflow. This is yaml.
NgTestReroute:
----path: /ng-test/{one}/{two}/{three}/{four}
----defaults:
--------_controller: DriverSideSiteBundle:NgTest:ngTestReroute
--------'one': null
--------'two': null
--------'three': null
--------'four': null
----methods: [GET]
在Symfony2控制器中,检查用户代理以查看它是googlebot还是bingbot。您应该可以使用下面的代码执行此操作,然后使用此列表定位您感兴趣的机器人(http://www.searchenginedictionary.com/spider-names.shtml)...
if(strstr(strtolower($_SERVER['HTTP_USER_AGENT']), "googlebot"))
{
// what to do
}
如果您的控制器找到与机器人匹配的内容,请将其发送给HTML代码段。否则,就像我的AngularJS应用程序一样,只需将用户发送到索引页面,Angular就会正确完成剩下的工作。
此外,如果您的问题已经得到解答,请选择一个,以便我和其他人可以说出对您有用的问题。
答案 3 :(得分:0)
我正在使用PhantomJS生成页面的静态快照。我的目录结构只有一层深(root
和/projects
),所以我有两个.htaccess文件,我在其中重定向到启动PhantomJS进程的PHP文件(index-bots.php
)指向我的SPA index.html
并打印出渲染的静态页面。
.htaccess文件如下所示:
<强> /。htaccess的强>
# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/index-bots\.php [NC]
RewriteRule ^(.*)$ index-bots.php?url=%{REQUEST_URI} [L,QSA]
<强> /projects/.htaccess 强>
# redirect search engine bots to index-bots.php
# in order to serve rendered HTML via phantomjs
RewriteCond %{HTTP_USER_AGENT} (bot|crawl|slurp|spider) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ../index-bots.php?url=%{REQUEST_URI} [L,QSA]
几点说明:
!-f
RewriteCond
至关重要!由于.htaccess会将RewriteRule
应用于所有请求,因此页面上的资源将被重写为PHP文件,从而启动PhantomJS的多个实例并使您的服务器瘫痪。index-bots.php
以避免无限循环也很重要。