4

我的SPA使用Backbone.js路由器,它使用 pushstate 和散列 URL 作为后备方法。我打算使用Google 的建议来制作 AJAX web-app crawlable。也就是说,我想将我的网站索引到PhantomJS生成的静态 .html 文件中,并通过 URL 将它们传递给 Google:

mysite.com/?_escaped_fragment_=key=value.

请记住,该站点不为最终用户提供静态页面(它仅适用于支持 Javascript 的浏览器)。如果您导航到mysite.com/some/url.htaccess文件,则设置为始终提供服务,mysite.com/index.php并且主干路由器将读取 URL 以显示该 URL 的 JavaScript 生成内容。

此外,为了让 Google 索引我的整个站点,我计划创建一个站点地图,该站点地图将是一个hashbang URL列表。URL 必须是 hashbanged,以便 Google 知道使用_escaped_fragment_key URL 索引该站点。

呜呜呜……

(1) 这种方法行得通吗?

(2) 由于backbone.js 不使用hashbang URL,当用户通过Google 到达时,如何将hashbang URL 转换为pushstate URL?

参考:https ://stackoverflow.com/a/6194427/1102215

4

2 回答 2

3

正如我在问题中概述的那样,我最终在实施过程中磕磕绊绊。所以...

(1)是的,这种方法似乎效果很好。唯一的缺点是即使应用程序在没有 hash-bangs 的情况下运行,我的 sitemap.xml 也充满了 hashbang URL。这是必要的,以提醒 Google 在抓取这些页面时应该查询 _escaped_fragment_ URL。因此,当该网站出现在 Google 搜索结果中时,URL 中会出现一个 hashbang,但这是一个很小的代价。

(2)这部分比我想象的要容易得多。在初始化 Backbone.js 路由器之前只需要一行代码......

window.location.hash = window.location.hash.replace(/#!/, '#');

var AppRouter = Backbone.Router.extend({...

将 hashbang 替换为仅一个 hash 后,主干路由器将自动删除支持 pushState 的浏览器的 hash。此外,这两个 URL 状态更改不会保存在浏览器的历史状态中,因此如果用户单击后退按钮,则不会出现异常/意外重定向。

更新:更好的方法

事实证明,有一种非常简单的方法可以完全消除 hashbangs。通过BromBone

如果您的网站使用 hashbangs (#!) 网址,那么 Google 将通过替换 #! 来抓取您的网站。使用 ?escaped_fragment=。当您看到 ?escaped_fragment= 时,您将知道该请求来自爬虫。如果您使用的是 html5 pushState,则查看“UserAgent”标头以确定请求是否来自机器人。

这是 BromBone 建议的 .htaccess 重写规则的修改版本:

    RewriteEngine On
    RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{HTTP_USER_AGENT} .*Googlebot.* [OR]
    RewriteCond %{HTTP_USER_AGENT} .*Bingbot.* [OR]
    RewriteCond %{HTTP_USER_AGENT} .*Baiduspider.* [OR]
    RewriteCond %{HTTP_USER_AGENT} .*iaskspider.*
    RewriteRule ^(.*)$ snapshot.php/$1 [L]
于 2013-12-19T23:30:36.563 回答
1

让我总结一下我在即将出版的关于 SPA 的书中写了大约 10 页的内容。Google 想要您网站的经典版本。这也是一个优势,因为过时的浏览器无论如何都无法有效地进行 SPA。为蜘蛛和旧浏览器提供核心站点。

我从 Gaurdian 报纸http://vimeo.com/channels/smashingconf得到这个词。

在浏览器中检查浏览器是否切了芥末,这是我的脚本:

<script>

    if (!('querySelector' in document)
         || !('localStorage' in window)
         || !('addEventListener' in window)
        || !('matchMedia' in window)) {

        if (window.location.href.indexOf("#!") > 0) {
            window.location.href = window.location.href.replace("#!", "?_escaped_fragment_=");
        } else {
            if (window.location.href.indexOf("?_escaped_fragment_=") < 0) {
                window.location.href = window.location.href + "?_escaped_fragment_=";
            }
        }

    } else {

        if (window.location.href.indexOf("?_escaped_fragment_=") >= 0) {
            window.location.href = window.location.href.replace("?_escaped_fragment_=", "#!");
        }
    }

</script>

在服务器上,您需要一些机制来检查 _escape_fragment_ 查询字符串是否存在。如果存在,您需要为核心站点提供服务。核心站点仅使用简单的 CSS 和很少或根本没有 JavaScript。我有一个用于 ASP.NET MVC 的 SPAHelper 库,您可以查看我在此方面实现的一些东西,https://github.com/docluv/spahelper

真正的问题是大多数服务器端 Web 框架(如 ASP.NET、PHP 等)并非旨在支持客户端和服务器的单一视图系统。所以你有点卡住了为此维护两个视图。我再次围绕这个主题为我的书写了大约 10 页,应该在下周的某个时间准备好。

于 2013-12-19T20:36:49.913 回答