Хотя №2 может быть «проще» для вас как разработчика, он обеспечивает только сканирование в поисковых системах. И да, если Google обнаружит, что вы обслуживаете другой контент, вас могут наказать (я не эксперт в этом, но слышал об этом).
Как SEO, так и доступность (не только для людей с ограниченными возможностями, но и с помощью мобильных устройств, устройств с сенсорным экраном и других нестандартных вычислительных платформ / платформ с подключением к Интернету) имеют схожую основную философию: семантически богатая разметка, которая «доступна» (т. Е. Может доступ, просмотр, чтение, обработка или иное использование) для всех этих различных браузеров. Программа чтения с экрана, сканер поисковой системы или пользователь с включенным JavaScript должны иметь возможность без проблем использовать / индексировать / понимать основные функции вашего сайта.
pushState
по моему опыту, не добавляет к этому бремени. Это только выводит то, что раньше было второстепенным, и «если у нас есть время» на передний план веб-разработки.
То, что вы описываете в варианте №1, обычно лучше всего, но, как и другие проблемы с доступностью и SEO, делать это с pushState
в приложении с большим количеством JavaScript требует предварительного планирования, иначе это станет серьезным бременем. Он должен быть встроен в архитектуру страницы и приложения с самого начала - модернизация болезненна и приведет к большему дублированию, чем необходимо.
Я работал с pushState
Недавно SEO для нескольких разных приложений, и я нашел то, что считаю хорошим подходом. Он в основном соответствует вашему пункту №1, но учитывает отсутствие дублирования html / шаблонов.
Большую часть информации можно найти в этих двух сообщениях блога:
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. Это исключает дублирование разметки между серверной и клиентской стороной.
Оттуда вам нужно предпринять несколько дополнительных шагов, чтобы ваш JavaScript работал с HTML, отображаемым сервером - истинное прогрессивное улучшение; взяв полученную семантическую разметку и улучшив ее с помощью JavaScript.
Например, я создаю приложение галереи изображений с помощью pushState
. Если вы запросите /images/1
с сервера, он отобразит всю галерею изображений на сервере и отправит все HTML, CSS и JavaScript в ваш браузер. Если у вас отключен JavaScript, он будет работать нормально. Каждое ваше действие будет запрашивать у сервера другой URL-адрес, и сервер будет отображать всю разметку для вашего браузера. Однако, если у вас включен 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>
Теперь вам нужно пройтись по этому списку и прикрепить представление и модель Backbone к каждому из <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
поддержки.
Надеюсь, это поможет.