Si bien el # 2 puede ser "más fácil" para usted como desarrollador, solo proporciona rastreo de motores de búsqueda. Y sí, si Google descubre que estás sirviendo contenido diferente, podrías ser penalizado (no soy un experto en eso, pero he oído que sucede).
Tanto el SEO como la accesibilidad (no solo para las personas discapacitadas, sino también la accesibilidad a través de dispositivos móviles, dispositivos de pantalla táctil y otras plataformas habilitadas para Internet / computación no estándar) tienen una filosofía subyacente similar: marcado semánticamente rico que es "accesible" (es decir, puede se puede acceder, ver, leer, procesar o utilizar de otro modo) a todos estos navegadores diferentes. Un lector de pantalla, un buscador de motores de búsqueda o un usuario con JavaScript habilitado, deberían poder usar / indexar / comprender la funcionalidad principal de su sitio sin problemas.
pushState
No agrega a esta carga, en mi experiencia. Solo trae lo que solía ser una idea de último momento y "si tenemos tiempo" a la vanguardia del desarrollo web.
Lo que describe en la opción n. ° 1 suele ser la mejor manera de hacerlo, pero, al igual que otros problemas de accesibilidad y SEO, hacerlo con pushState
una aplicación con mucho JavaScript requiere una planificación inicial o se convertirá en una carga significativa. Debe integrarse en la página y la arquitectura de la aplicación desde el principio: la modificación es dolorosa y causará más duplicación de la necesaria.
He estado trabajando con pushState
SEO recientemente para un par de aplicaciones diferentes, y encontré lo que creo que es un buen enfoque. Básicamente sigue a su elemento # 1, pero explica no duplicar html / templates.
La mayor parte de la información se puede encontrar en estas dos publicaciones de blog:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
y
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
La esencia de esto es que uso plantillas ERB o HAML (ejecutando Ruby on Rails, Sinatra, etc.) para mi render del lado del servidor y para crear las plantillas del lado del cliente que Backbone puede usar, así como para mis especificaciones JavaScript de Jasmine. Esto elimina la duplicación de marcado entre el lado del servidor y el lado del cliente.
A partir de ahí, debe seguir algunos pasos adicionales para que su JavaScript funcione con el HTML que representa el servidor: verdadera mejora progresiva; tomar el marcado semántico que se entregó y mejorarlo con JavaScript.
Por ejemplo, estoy creando una aplicación de galería de imágenes con pushState
. Si lo solicita /images/1
desde el servidor, renderizará toda la galería de imágenes en el servidor y enviará todo el HTML, CSS y JavaScript a su navegador. Si tiene JavaScript deshabilitado, funcionará perfectamente bien. Cada acción que realice solicitará una URL diferente del servidor y el servidor representará todo el marcado para su navegador. Sin embargo, si tiene habilitado JavaScript, el JavaScript recogerá el HTML ya representado junto con algunas variables generadas por el servidor y se hará cargo de allí.
Aquí hay un ejemplo:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Después de que el servidor procesa esto, el JavaScript lo recogerá (usando una vista Backbone.js en este ejemplo)
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")
});
});
Este es un ejemplo muy simple, pero creo que se entiende.
Cuando instalo la vista una vez que se carga la página, proporciono el contenido existente del formulario que fue presentado por el servidor, a la instancia de vista como el
para la vista. Estoy no llamando render o tener la vista genere una el
para mí, cuando se carga la primera vista. Tengo un método de renderizado disponible después de que la vista esté en funcionamiento y la página sea todo JavaScript. Esto me permite volver a renderizar la vista más tarde si es necesario.
Al hacer clic en el botón "Decir mi nombre" con JavaScript habilitado, aparecerá un cuadro de alerta. Sin JavaScript, se volvería a publicar en el servidor y el servidor podría representar el nombre de un elemento html en alguna parte.
Editar
Considere un ejemplo más complejo, donde tiene una lista que debe adjuntarse (de los comentarios a continuación)
Digamos que tiene una lista de usuarios en una <ul>
etiqueta. El servidor prestó esta lista cuando el navegador realizó una solicitud y el resultado se parece a:
<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>
Ahora debe recorrer esta lista y adjuntar una vista Backbone y un modelo a cada uno de los <li>
elementos. Con el uso del data-id
atributo, puede encontrar fácilmente el modelo del que proviene cada etiqueta. Luego, necesitará una vista de colección y una vista de elemento que sea lo suficientemente inteligente como para adjuntarse a este html.
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();
En este ejemplo, UserListView
recorrerá todas las <li>
etiquetas y adjuntará un objeto de vista con el modelo correcto para cada una. configura un controlador de eventos para el evento de cambio de nombre del modelo y actualiza el texto visualizado del elemento cuando se produce un cambio.
Este tipo de proceso, para tomar el html que el servidor renderizó y hacer que mi JavaScript se haga cargo y lo ejecute, es una excelente manera de hacer que las cosas funcionen para SEO, accesibilidad y pushState
soporte.
Espero que ayude.