历史PushState API不支持url中的长片段

时间:2018-01-26 22:22:00

标签: javascript html5 backbone.js pushstate

目前,我的应用程序在Backbone.js上运行。

该应用程序适用于#片段,但由于网址中的#,因此谷歌机器人无法对其进行抓取。

所以,我决定删除#以使其更适合SEO。我启用了History pushState API并添加了代码以防止默认操作。这是我初始化路由器实例时的代码片段。

Backbone.history.start({pushState: true});

$(document).on("click", "a", function(e)
        {

            var href = $(e.currentTarget).attr('href');

            var res = Backbone.history.navigate(href,true);
            //if we have an internal route don't call the server
            if(res)
                e.preventDefault();

        });

此外,我修改了我的Apache配置以启用mod_rewrite,以便处理无状态请求,例如刷新页面或将页面打开到新的浏览器窗口。这是我的Apache配置代码段:

 <IfModule mod_rewrite.c>
            RewriteEngine on
            RewriteRule ^/([a-zA-Z0-9]+)[/]?$ /index.html?pathtyped=$1 [QSA,L]
 </IfModule>

我面临的问题是,应用程序可以很好地处理短网址碎片,但它们不适用于大碎片。意味着以下网址的工作原理:

http:server_name/#view1 - &gt; http:server_name/view1

http:server_name/#view2 - &gt; http:server_name/view2

http:server_name/#view3 - &gt; http:server_name/view3

但是长片段的网址不起作用。 (以下不做):

http:server_name/#view1/option1 - &gt; http:server_name/view1/option1

http:server_name/#view2/option1/option2 - &gt; http:server_name/view2/option1/option2

非常感谢任何解决问题的建议。谢谢你!

3 个答案:

答案 0 :(得分:2)

我做了一些谷歌搜索并最终偶然发现this gist。我用最小的Backbone.js应用程序测试了它,它似乎支持无限长的无状态进入应用程序:

<ifModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !index
    RewriteRule .* index.html [L,QSA]
</ifModule>

我必须做一些阅读才能完全理解RewriteCond语句,特别是!-f-d!index正在做什么。除!index之外的所有内容都有意义。

试一试,让我知道它是否适合你。

编辑:我实际上发现上面只能在我的Mac上安装我的Homebrew安装的Apache2版本,而不是在Debian上。更多谷歌搜索产生了这种替代形式:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</IfModule>

我还用pushState和无状态条目here组合了一个现代Backbone.js应用程序的完整工作示例。

答案 1 :(得分:1)

我猜测应用程序在http://server_name/viewX之类的单个URL组件方案中工作,因为您定义的Backbone.Router与URL匹配并成功匹配,并使回调定义为呈现viewX (对于现代浏览器和网络抓取工具,没有#,对于旧浏览器,没有Backbone.Router.routes。因此,当它不起作用时,我会想象定义的路由模式与预期的嵌套URL组件不匹配,并且不会触发渲染回调。

您可能需要查看routes: { view(/:option1)(/:option2) : renderView } 哈希值,并确保您的模式与每个深度处的预期网址组件相匹配。查看Backbone documentation on routes,特别是关于可选和嵌套URL组件的示例,并检查您的匹配模式是否正确。例如,路由哈希包含:

view

应匹配以#view(或view/1)开头的网址,并可选择包含一个或两个子参数,例如:

  • view/1/a
  • #view/1
  • #view/1/a
  • option1

在上面的示例中,1将被分配option2a将被分配routes: { view/*option1 : renderView } ,并将被传递给回调。

使用类似的路由哈希:

/

第一个option1之外的所有内容都会匹配并分配给view/1/a,例如:

  • #view/1/a
  • option1

在上述两种情况下,1/a都会被赋予字符串{{1}},并会传递给回调。

答案 2 :(得分:-1)

嗯......也许这很有用(基于幻影):http://traviswimer.com/blog/backbone-seo