最近では、強力な「シングルページ」JavaScript Web サイトを作成するための優れたツールが数多くあります。私の意見では、サーバーを API として機能させ (それ以上のことはせず)、クライアントに HTML 生成のすべてを処理させることで、この作業は適切に行われます。この「パターン」の問題は、検索エンジンのサポートがないことです。次の 2 つの解決策が考えられます。
- ユーザーが Web サイトにアクセスすると、ナビゲーション時にクライアントが行うのとまったく同じように、サーバーがページをレンダリングします。つまり、直接アクセスすると、pushState 経由で
http://example.com/my_path
アクセスした場合と同じように、サーバーがレンダリングします。/my_path
- サーバーが検索エンジン ボット専用の特別な Web サイトを提供するようにします。通常のユーザーがアクセスした場合、
http://example.com/my_path
サーバーは Web サイトの JavaScript を多用したバージョンを提供する必要があります。ただし、Google ボットがアクセスした場合、サーバーは Google にインデックスさせたいコンテンツを含む最小限の HTML を提供する必要があります。
最初の解決策についてはさらに議論するここ私はこれを実行する Web サイトで作業していますが、あまり良い経験ではありません。これは DRY ではなく、私の場合はクライアントとサーバーに 2 つの異なるテンプレート エンジンを使用する必要がありました。
古き良き Flash ウェブサイトで 2 番目のソリューションを見たことがあると思います。このアプローチは最初のアプローチよりもずっと気に入っています。サーバーに適切なツールがあれば、非常に簡単に実行できます。
私が本当に疑問に思っているのは次のことです。
- もっと良い解決策を思いつきますか?
- 2 番目の解決策の欠点は何ですか? Google が何らかの方法で、私が Google ボットに通常のユーザーとまったく同じコンテンツを提供していないことを知った場合、検索結果でペナルティを受けることになりますか?
ベストアンサー1
開発者にとっては、2 番の方が「簡単」かもしれませんが、検索エンジンのクロールしか提供されません。また、Google が別のコンテンツを提供していることを発見した場合、ペナルティを受ける可能性があります (私はその分野の専門家ではありませんが、実際に起こったという話は聞いたことがあります)。
SEO とアクセシビリティ (身体障がい者だけでなく、モバイル デバイス、タッチ スクリーン デバイス、その他の非標準コンピューティング/インターネット対応プラットフォーム経由のアクセシビリティ) はどちらも、同様の基本理念を持っています。つまり、さまざまなブラウザーすべてに対して「アクセス可能」(つまり、アクセス、表示、読み取り、処理、その他の使用が可能) な意味的にリッチなマークアップです。スクリーン リーダー、検索エンジン クローラー、または JavaScript が有効になっているユーザーは、すべて問題なくサイトのコア機能を使用/インデックス作成/理解できる必要があります。
pushState
私の経験では、この負担が増えることはありません。これは、これまでは後回しにし、「時間があれば」と考えていたことを、Web 開発の最前線に持ち込むだけです。
オプション 1 で説明した内容は、通常は最善の方法ですが、他のアクセシビリティや SEO の問題と同様に、pushState
JavaScript を多用するアプリ内でこれを実行するには事前の計画が必要であり、そうしないと大きな負担になります。最初からページとアプリケーションのアーキテクチャに組み込む必要があります。後付けは面倒で、必要以上に重複が発生します。
最近、いくつかの異なるアプリケーションで SEOに取り組んできましたpushState
が、良いアプローチだと思われるものを見つけました。基本的には項目 1 に従いますが、HTML / テンプレートが重複しないように考慮されています。
ほとんどの情報は、次の 2 つのブログ投稿で見つかります。
そして
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 になった後には、レンダリング メソッドを使用できます。これにより、必要に応じて後でビューを再レンダリングできます。
JavaScript を有効にして「名前を言う」ボタンをクリックすると、警告ボックスが表示されます。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>
アイテムに Backbone ビューとモデルをアタッチする必要があります。属性を使用すると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
。
お役に立てれば幸いです。