Bien que le n ° 2 puisse être «plus facile» pour vous en tant que développeur, il ne fournit que l'exploration des moteurs de recherche. Et oui, si Google découvre que vous diffusez un contenu différent, vous pourriez être pénalisé (je ne suis pas un expert en la matière, mais j'en ai entendu parler).
Le référencement et l'accessibilité (pas seulement pour les personnes handicapées, mais aussi l'accessibilité via des appareils mobiles, des appareils à écran tactile et d'autres plates-formes informatiques / Internet non standard) ont tous deux une philosophie sous-jacente similaire: un balisage sémantiquement riche qui est «accessible» (c.-à-d. être consultés, consultés, lus, traités ou autrement utilisés) à tous ces différents navigateurs. Un lecteur d'écran, un robot d'exploration de moteur de recherche ou un utilisateur avec JavaScript activé, devraient tous être capables d'utiliser / indexer / comprendre les fonctionnalités de base de votre site sans problème.
pushState
n'ajoute pas à ce fardeau, d'après mon expérience. Cela ne fait qu'apporter ce qui était autrefois une réflexion après coup et "si nous en avons le temps" au premier plan du développement Web.
Ce que vous décrivez dans l'option n ° 1 est généralement la meilleure façon de procéder - mais, comme d'autres problèmes d'accessibilité et de référencement, le faire pushState
dans une application contenant beaucoup de JavaScript nécessite une planification préalable , sinon cela deviendra un fardeau important. Il doit être intégré à la page et à l'architecture de l'application dès le début - la mise à niveau est douloureuse et entraînera plus de duplication que nécessaire.
J'ai pushState
récemment travaillé avec et SEO pour quelques applications différentes, et j'ai trouvé ce que je pense être une bonne approche. Il suit essentiellement votre élément n ° 1, mais tient compte de la non duplication du HTML / des modèles.
La plupart des informations se trouvent dans ces deux articles de blog:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
et
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
L'essentiel est que j'utilise des modèles ERB ou HAML (exécutant Ruby on Rails, Sinatra, etc.) pour mon rendu côté serveur et pour créer les modèles côté client que Backbone peut utiliser, ainsi que pour mes spécifications JavaScript Jasmine. Cela supprime la duplication du balisage entre le côté serveur et le côté client.
À partir de là, vous devez prendre quelques étapes supplémentaires pour que votre JavaScript fonctionne avec le HTML rendu par le serveur - une véritable amélioration progressive; prendre le balisage sémantique qui a été livré et l'améliorer avec JavaScript.
Par exemple, je crée une application de galerie d'images avec pushState
. Si vous demandez /images/1
au serveur, il rendra toute la galerie d'images sur le serveur et enverra tout le HTML, CSS et JavaScript à votre navigateur. Si vous avez désactivé JavaScript, cela fonctionnera parfaitement. Chaque action que vous entreprenez demandera une URL différente au serveur et le serveur rendra tout le balisage pour votre navigateur. Si vous avez activé JavaScript, cependant, le JavaScript récupérera le HTML déjà rendu avec quelques variables générées par le serveur et prendra le relais à partir de là.
Voici un exemple:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Une fois que le serveur a rendu cela, le JavaScript le récupère (en utilisant une vue Backbone.js dans cet exemple)
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")
});
});
C'est un exemple très simple, mais je pense qu'il fait passer le message.
Lorsque j'instante la vue après le chargement de la page, je fournis le contenu existant du formulaire rendu par le serveur, à l'instance de vue comme el
pour la vue. Je n'appelle pas render ou je ne demande pas à la vue de générer un el
pour moi, lorsque la première vue est chargée. J'ai une méthode de rendu disponible une fois que la vue est opérationnelle et que la page est entièrement en JavaScript. Cela me permet de restituer la vue plus tard si j'en ai besoin.
Cliquer sur le bouton "Dites mon nom" avec JavaScript activé provoquera une boîte d'alerte. Sans JavaScript, il serait posté sur le serveur et le serveur pourrait rendre le nom en un élément html quelque part.
Éditer
Prenons un exemple plus complexe, où vous avez une liste qui doit être jointe (à partir des commentaires ci-dessous)
Supposons que vous ayez une liste d'utilisateurs dans une <ul>
balise. Cette liste a été rendue par le serveur lorsque le navigateur a fait une demande, et le résultat ressemble à quelque chose comme:
<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>
Vous devez maintenant parcourir cette liste et attacher une vue et un modèle Backbone à chacun des <li>
éléments. Avec l'utilisation de l' data-id
attribut, vous pouvez trouver facilement le modèle dont provient chaque balise. Vous aurez alors besoin d'une vue de collection et d'une vue d'élément suffisamment intelligentes pour s'attacher à ce code 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();
Dans cet exemple, le UserListView
parcourt toutes les <li>
balises et attache un objet de vue avec le modèle correct pour chacun. il configure un gestionnaire d'événements pour l'événement de changement de nom du modèle et met à jour le texte affiché de l'élément lorsqu'une modification se produit.
Ce type de processus, pour prendre le html rendu par le serveur et faire prendre en charge mon JavaScript et l'exécuter, est un excellent moyen de faire avancer les choses pour le référencement, l'accessibilité et le pushState
support.
J'espère que cela pourra aider.