#2 は開発者にとって「簡単」かもしれませんが、検索エンジンのクロールのみを提供します。そしてもちろん、Google があなたが別のコンテンツを配信していることを発見した場合、あなたは罰せられる可能性があります (私はその専門家ではありませんが、実際に起こっていると聞いたことがあります)。
SEO とアクセシビリティ (障害者だけでなく、モバイル デバイス、タッチ スクリーン デバイス、およびその他の非標準のコンピューティング/インターネット対応プラットフォームを介したアクセシビリティ) には、どちらも同様の根本的な哲学があります。これらすべての異なるブラウザに スクリーン リーダー、検索エンジン クローラー、または JavaScript が有効になっているユーザーは、サイトのコア機能を問題なく使用/インデックス作成/理解できる必要があります。
pushState
私の経験では、この負担が増えることはありません。これまでは後付けで、「時間があれば」ということを Web 開発の最前線に持ち込むだけです。
オプション #1 で説明することが通常は最善の方法ですが、他のアクセシビリティや SEO の問題と同様pushState
に、JavaScript を多用するアプリでこれを行うには、事前の計画が必要です。そうしないと、かなりの負担になります。最初からページとアプリケーション アーキテクチャに組み込む必要があります。レトロフィットは苦痛であり、必要以上の重複が発生します。
私はpushState
最近、いくつかの異なるアプリケーションで SEO に取り組んできましたが、良いアプローチだと思うものを見つけました。基本的にあなたの項目#1に従いますが、html /テンプレートを複製しないことを考慮しています。
ほとんどの情報は、次の 2 つのブログ投稿で見つけることができます。
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
と
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
その要点は、サーバー側のレンダリングに ERB または HAML テンプレート (Ruby on Rails、Sinatra などを実行) を使用し、Backbone が使用できるクライアント側のテンプレートを作成することと、Jasmine JavaScript 仕様に使用することです。これにより、サーバー側とクライアント側の間でマークアップの重複がなくなります。
そこから、サーバーによってレンダリングされる HTML で JavaScript を機能させるために、いくつかの追加手順を実行する必要があります。配信されたセマンティック マークアップを取得し、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>
サーバーがこれをレンダリングした後、JavaScript がそれを取得します (この例では Backbone.js ビューを使用)。
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")
});
});
これは非常に単純な例ですが、要点を理解していると思います。
ページの読み込み後にビューをインスタンス化すると、サーバーによってレンダリングされたフォームの既存のコンテンツが、ビューのインスタンスとしてビュー インスタンスに提供されel
ます。最初のビューがロードされたときに、レンダリングを呼び出したり、ビューに生成させたりしていません。el
ビューが起動して実行され、ページがすべて JavaScript になった後に使用できる render メソッドがあります。これにより、後で必要に応じてビューを再レンダリングできます。
JavaScript を有効にして [Say My Name] ボタンをクリックすると、警告ボックスが表示されます。JavaScript がないと、サーバーにポストバックされ、サーバーは名前をどこかの html 要素にレンダリングできます。
編集
添付する必要があるリストがある、より複雑な例を考えてみましょう(この下のコメントから)
<ul>
タグにユーザーのリストがあるとします。このリストは、ブラウザがリクエストを行ったときにサーバーによってレンダリングされたもので、結果は次のようになります。
<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>
次に、このリストをループして、バックボーン ビューとモデルを各<li>
アイテムにアタッチする必要があります。属性を使用すると、data-id
各タグが由来するモデルを簡単に見つけることができます。次に、この 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();
この例では、UserListView
はすべてのタグをループし<li>
、それぞれに正しいモデルを持つビュー オブジェクトをアタッチします。モデルの名前変更イベントのイベント ハンドラーを設定し、変更が発生したときに要素の表示テキストを更新します。
この種のプロセスは、サーバーがレンダリングした html を受け取り、それを JavaScript に引き継いで実行させるというもので、SEO、アクセシビリティ、およびpushState
サポートのために物事を進めるための優れた方法です。
それが役立つことを願っています。