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.
Creo que necesitas esto: http://code.google.com/web/ajaxcrawling/
También puede instalar un backend especial que "renderiza" su página ejecutando javascript en el servidor, y luego lo sirve en google.
Combina ambas cosas y tendrás una solución sin programar dos veces. (Siempre que su aplicación sea totalmente controlable a través de fragmentos de anclaje).
fuente
Entonces, parece que la principal preocupación es estar SECO
<a href="https://stackoverflow.com/someotherpage">mylink</a>
, el servidor reescribe la url en su archivo de aplicación, la carga en phantom.js y el html resultante se envía al bot, y así sucesivamente. ..<a>
etiquetas. En este caso, manejar 404 es más fácil ya que simplemente puede verificar la existencia del archivo estático con un nombre que contiene la ruta de URL.Aquí hay un par de ejemplos que usan phantom.js para seo:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
fuente
Si usa Rails, intente poirot . Es una gema que hace que sea muy simple reutilizar las plantillas de bigote o manillar del lado del cliente y del servidor.
Crea un archivo en tus vistas como
_some_thingy.html.mustache
.Render del lado del servidor:
Ponga la plantilla de su cabeza para uso del lado del cliente:
Rendre lado del cliente:
fuente
Para tomar un ángulo ligeramente diferente, su segunda solución sería la correcta en términos de accesibilidad ... proporcionaría contenido alternativo a los usuarios que no pueden usar JavaScript (aquellos con lectores de pantalla, etc.).
Esto agregaría automáticamente los beneficios del SEO y, en mi opinión, Google no lo consideraría una técnica "traviesa".
fuente
Interesante. He estado buscando soluciones viables, pero parece ser bastante problemático.
De hecho, me estaba inclinando más hacia su segundo enfoque:
Aquí está mi opinión sobre la resolución del problema. Aunque no está confirmado que funcione, puede proporcionar alguna idea o idea para otros desarrolladores.
Suponga que está utilizando un marco JS que admite la funcionalidad de "estado de inserción", y su marco de back-end es Ruby on Rails. Tiene un sitio de blog simple y desea que los motores de búsqueda indexen todos sus artículos
index
yshow
páginas.Digamos que tienes tus rutas configuradas así:
Asegúrese de que cada controlador del lado del servidor muestre la misma plantilla que su marco del lado del cliente requiere para ejecutarse (html / css / javascript / etc). Si ninguno de los controladores coincide con la solicitud (en este ejemplo, solo tenemos un conjunto RESTful de acciones para el
ArticlesController
), simplemente empareje cualquier otra cosa y solo renderice la plantilla y deje que el marco del lado del cliente maneje el enrutamiento. La única diferencia entre golpear un controlador y golpear el comodín sería la capacidad de representar el contenido en función de la URL que se solicitó a los dispositivos con JavaScript deshabilitado.Por lo que entiendo, es una mala idea presentar contenido que no sea visible para los navegadores. Entonces, cuando Google lo indexa, las personas pasan por Google para visitar una página determinada y no hay ningún contenido, entonces es probable que lo penalicen. Lo que viene a la mente es que renderizas contenido en un
div
nodo que tienesdisplay: none
en CSS.Sin embargo, estoy bastante seguro de que no importa si simplemente haces esto:
Y luego usando JavaScript, que no se ejecuta cuando un dispositivo con JavaScript deshabilitado abre la página:
De esta manera, para Google y para cualquier persona con dispositivos con JavaScript deshabilitado, verían el contenido sin formato / estático. Por lo tanto, el contenido está físicamente allí y es visible para cualquier persona con dispositivos con JavaScript deshabilitado.
Pero, cuando un usuario visita la misma página y en realidad tiene JavaScript habilitado, el
#no-js
nodo se eliminará para que no sature su aplicación. Luego, su marco del lado del cliente manejará la solicitud a través de su enrutador y mostrará lo que un usuario debería ver cuando JavaScript esté habilitado.Creo que esta podría ser una técnica válida y bastante fácil de usar. Aunque eso podría depender de la complejidad de su sitio web / aplicación.
Sin embargo, corrígeme si no es así. Solo pensé en compartir mis pensamientos.
fuente
Use NodeJS en el lado del servidor, busque su código del lado del cliente y enrute cada uri de solicitud http (excepto los recursos http estáticos) a través de un cliente del lado del servidor para proporcionar el primer 'arranque' (una instantánea de la página en que se encuentra). Use algo como jsdom para manejar jquery dom-ops en el servidor. Una vez que haya regresado el arranque, configure la conexión websocket. Probablemente sea mejor diferenciar entre un cliente websocket y un cliente del lado del servidor haciendo algún tipo de conexión envolvente en el lado del cliente (el cliente del lado del servidor puede comunicarse directamente con el servidor). He estado trabajando en algo como esto: https://github.com/jvanveen/rnet/
fuente
Use la plantilla de cierre de Google para representar páginas. Se compila a javascript o java, por lo que es fácil renderizar la página en el lado del cliente o del servidor. En el primer encuentro con cada cliente, renderice el html y agregue javascript como enlace en el encabezado. El rastreador solo leerá el html pero el navegador ejecutará su script. Todas las solicitudes posteriores del navegador podrían realizarse contra la API para minimizar el tráfico.
fuente