Mentre # 2 potrebbe essere "più facile" per te come sviluppatore, fornisce solo la scansione dei motori di ricerca. E sì, se Google scopre che stai offrendo diversi contenuti, potresti essere penalizzato (non ne sono un esperto, ma ne ho sentito parlare).
Sia la SEO che l'accessibilità (non solo per le persone disabili, ma l'accessibilità tramite dispositivi mobili, dispositivi touchscreen e altre piattaforme informatiche / abilitate per Internet) hanno entrambe una filosofia di base simile: markup semanticamente ricco che è "accessibile" (cioè può essere accessibile, visualizzato, letto, elaborato o utilizzato in altro modo) su tutti questi diversi browser. Uno screen reader, un crawler del motore di ricerca o un utente con JavaScript abilitato, dovrebbero essere tutti in grado di utilizzare / indicizzare / comprendere le funzionalità principali del tuo sito senza problemi.
pushState
non aggiunge a questo onere, nella mia esperienza. Porta solo ciò che era un ripensamento e "se abbiamo tempo" in prima linea nello sviluppo web.
Quello che descrivi nell'opzione n. 1 è di solito il modo migliore di procedere, ma, come altri problemi di accessibilità e SEO, farlo con pushState
un'app pesante di JavaScript richiede una pianificazione anticipata o diventerà un onere significativo. Dovrebbe essere inserito nella pagina e nell'architettura dell'applicazione dall'inizio: il retrofit è doloroso e causerà più duplicazioni del necessario.
Di pushState
recente ho lavorato con SEO per un paio di applicazioni diverse e ho trovato quello che penso sia un buon approccio. Fondamentalmente segue il tuo articolo n. 1, ma tiene conto della non duplicazione di html / template.
La maggior parte delle informazioni sono disponibili in questi due post di blog:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
e
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
L'essenza di ciò è che uso i modelli ERB o HAML (che eseguono Ruby on Rails, Sinatra, ecc.) Per il mio rendering lato server e per creare i modelli lato client che Backbone può usare, così come per le mie specifiche JavaScript di Jasmine. Ciò elimina la duplicazione del markup tra il lato server e il lato client.
Da lì, devi fare alcuni passi aggiuntivi per far funzionare il tuo JavaScript con l'HTML reso dal server - vero miglioramento progressivo; prendendo il markup semantico che è stato consegnato e migliorandolo con JavaScript.
Ad esempio, sto creando un'applicazione per la galleria di immagini con pushState
. Se richiesto /images/1
dal server, eseguirà il rendering dell'intera galleria di immagini sul server e invierà tutto il codice HTML, CSS e JavaScript fino al browser. Se JavaScript è disabilitato, funzionerà perfettamente. Ogni azione intrapresa richiederà un URL diverso dal server e il server renderà tutto il markup per il tuo browser. Se hai JavaScript abilitato, tuttavia, JavaScript prenderà l'HTML già renderizzato insieme ad alcune variabili generate dal server e subentrerà da lì.
Ecco un esempio:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Dopo il rendering del server, JavaScript lo raccoglierà (usando una vista Backbone.js in questo esempio)
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")
});
});
Questo è un esempio molto semplice, ma penso che ottenga il punto.
Quando installo la vista dopo il caricamento della pagina, sto fornendo il contenuto esistente del modulo che è stato reso dal server, all'istanza della vista come el
per la vista. Non sto chiamando render o non ho la vista generare un el
per me, quando viene caricata la prima vista. Ho un metodo di rendering disponibile dopo che la vista è attiva e funzionante e la pagina è tutta JavaScript. Questo mi consente di visualizzare nuovamente la vista in un secondo momento, se necessario.
Facendo clic sul pulsante "Pronuncia il mio nome" con JavaScript abilitato, verrà visualizzata una finestra di avviso. Senza JavaScript, sarebbe postare di nuovo sul server e il server potrebbe rendere il nome su un elemento HTML da qualche parte.
modificare
Considera un esempio più complesso, in cui hai un elenco che deve essere allegato (dai commenti sotto questo)
Supponi di avere un elenco di utenti in un <ul>
tag. Questo elenco è stato reso dal server quando il browser ha effettuato una richiesta e il risultato è simile al seguente:
<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>
Ora è necessario scorrere questo elenco e collegare una vista e un modello Backbone a ciascuno degli <li>
elementi. Con l'uso data-id
dell'attributo, puoi trovare facilmente il modello da cui proviene ogni tag. Avrai quindi bisogno di una vista raccolta e di un elemento abbastanza intelligente da collegarsi a questo 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();
In questo esempio, UserListView
eseguirà il ciclo tra tutti i <li>
tag e allegherà un oggetto vista con il modello corretto per ognuno. imposta un gestore eventi per l'evento di modifica del nome del modello e aggiorna il testo visualizzato dell'elemento quando si verifica una modifica.
Questo tipo di processo, per prendere l'html reso dal server e far sì che il mio JavaScript prenda il sopravvento e lo esegua, è un ottimo modo per far girare le cose per SEO, accessibilità e pushState
supporto.
Spero che aiuti.