Javascript &引用;单页“;JS网站与搜索引擎优化
现在有很多很酷的工具来创建强大的“单页”JavaScript网站。在我看来,让服务器充当API(仅此而已)并让客户机处理所有HTML生成内容是正确的。这种“模式”的问题在于缺乏搜索引擎支持。我可以想出两种解决办法:Javascript &引用;单页“;JS网站与搜索引擎优化,javascript,seo,backbone.js,pushstate,singlepage,Javascript,Seo,Backbone.js,Pushstate,Singlepage,现在有很多很酷的工具来创建强大的“单页”JavaScript网站。在我看来,让服务器充当API(仅此而已)并让客户机处理所有HTML生成内容是正确的。这种“模式”的问题在于缺乏搜索引擎支持。我可以想出两种解决办法: 当用户进入网站时,让服务器完全按照客户端在导航时的方式呈现页面。所以如果我去http://example.com/my_path如果我通过pushState转到/my_path,服务器将直接呈现与客户端相同的内容 让服务器只为搜索引擎机器人提供一个特殊的网站。如果普通用户访问http
http://example.com/my_path
如果我通过pushState转到/my_path
,服务器将直接呈现与客户端相同的内容http://example.com/my_path
服务器应该给他一个JavaScript版本的网站。但是如果谷歌机器人访问,服务器应该给它一些最小的HTML,其中包含我希望谷歌索引的内容- 你能想出更好的解决办法吗
- 第二种解决方案的缺点是什么?如果谷歌以某种方式发现我没有像普通用户一样为谷歌机器人提供完全相同的内容,我会在搜索结果中受到惩罚吗
pushState
不会增加这个负担。它只会将过去的事后思考和“如果我们有时间”带到web开发的前沿
选项1中描述的内容通常是最好的方法,但是,与其他可访问性和SEO问题一样,在JavaScript应用程序中使用pushState
进行此操作需要预先规划,否则将成为一个沉重的负担。它应该从一开始就嵌入到页面和应用程序体系结构中——改装是痛苦的,并且会导致更多的重复
我最近一直在为几个不同的应用程序使用pushState
和SEO,我发现我认为这是一个很好的方法。它基本上遵循您的条目#1,但不会复制html/模板
大部分信息可在以下两篇博文中找到:
及
其要点是,我使用ERB或HAML模板(运行Ruby on Rails、Sinatra等)进行服务器端渲染,创建主干网可以使用的客户端模板,以及Jasmine JavaScript规范。这就减少了服务器端和客户端之间标记的重复
从这里开始,您需要采取一些额外的步骤,让JavaScript处理由服务器呈现的HTML—真正的渐进增强;获取交付的语义标记,并使用JavaScript对其进行增强
例如,我正在使用pushState
构建一个图像库应用程序。如果您从服务器请求/images/1
,它将在服务器上呈现整个图像库,并将所有HTML、CSS和JavaScript发送到浏览器。如果禁用了JavaScript,它将工作得非常好。您执行的每个操作都将从服务器请求不同的URL,服务器将为您的浏览器呈现所有标记。但是,如果启用了JavaScript,JavaScript将获取已经呈现的HTML以及服务器生成的一些变量,并从中接管
下面是一个例子:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
这是一个非常简单的例子,但我认为它能说明问题
当我在页面加载后实例化视图时,我将把服务器呈现的表单的现有内容作为视图的el
提供给视图实例。当加载第一个视图时,我没有调用render或让视图为我生成el
。我有一个渲染方法,可以在视图启动并运行之后使用,页面都是JavaScript。这使我可以在以后需要时重新渲染视图
使用JavaScript单击“说出我的名字”按钮
FooView = Backbone.View.extend({
events: {
"change #name": "setName",
"click #say": "sayName"
},
setName: function(e){
var name = $(e.currentTarget).val();
this.model.set({name: name});
},
sayName: function(e){
e.preventDefault();
var name = this.model.get("name");
alert("Hello " + name);
},
render: function(){
// do some rendering here, for when this is just running JavaScript
}
});
$(function(){
var model = new MyModel();
var view = new FooView({
model: model,
el: $("#foo")
});
});
<ul id="user-list">
<li data-id="1">Bob
<li data-id="2">Mary
<li data-id="3">Frank
<li data-id="4">Jane
</ul>
UserListView = Backbone.View.extend({
attach: function(){
this.el = $("#user-list");
this.$("li").each(function(index){
var userEl = $(this);
var id = userEl.attr("data-id");
var user = this.collection.get(id);
new UserView({
model: user,
el: userEl
});
});
}
});
UserView = Backbone.View.extend({
initialize: function(){
this.model.bind("change:name", this.updateName, this);
},
updateName: function(model, val){
this.el.text(val);
}
});
var userData = {...};
var userList = new UserCollection(userData);
var userListView = new UserListView({collection: userList});
userListView.attach();
<%= render :partial => 'some_thingy', object: my_model %>
<%= template_include_tag 'some_thingy' %>
html = poirot.someThingy(my_model)
resources :articles
match "*path", "main#index"
<div id="no-js">
<h1><%= @article.title %></h1>
<p><%= @article.description %></p>
<p><%= @article.content %></p>
</div>
$("#no-js").remove() # jQuery