Хотя №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
поддержки.
Надеюсь, это поможет.
Думаю, вам это нужно: http://code.google.com/web/ajaxcrawling/
Вы также можете установить специальный бэкэнд, который «отображает» вашу страницу, запустив javascript на сервере, а затем обслуживает его в Google.
Объедините обе вещи, и вы получите решение без двойного программирования. (Если ваше приложение полностью управляется с помощью фрагментов привязки.)
источник
Итак, похоже, что основная проблема - это СУХОЙ
<a href="https://stackoverflow.com/someotherpage">mylink</a>
, сервер перезаписывает URL-адрес вашего файла приложения, загружает его в phantom.js, и полученный html отправляется боту, и так далее. ..<a>
теги. В этом случае обработка 404 упрощается, так как вы можете просто проверить наличие статического файла с именем, содержащим путь URL.Вот пара примеров использования phantom.js для поисковой оптимизации:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
источник
Если вы используете Rails, попробуйте poirot . Это драгоценный камень, который упрощает повторное использование шаблонов усов или ручек на стороне клиента и сервера.
Создайте файл в ваших представлениях вроде
_some_thingy.html.mustache
.Рендеринг на стороне сервера:
Поместите шаблон в голову для использования на стороне клиента:
Клиентская часть Rendre:
источник
Если взглянуть немного под другим углом, ваше второе решение будет правильным с точки зрения доступности ... вы будете предоставлять альтернативный контент пользователям, которые не могут использовать javascript (те, у кого есть программы чтения с экрана и т. Д.).
Это автоматически добавит преимуществ SEO и, на мой взгляд, не будет рассматриваться Google как «непослушный» метод.
источник
Интересный. Я искал жизнеспособные решения, но это кажется довольно проблематичным.
На самом деле я больше склонялся к вашему второму подходу:
Вот мой взгляд на решение проблемы. Хотя это не подтверждено как работающее, оно может дать некоторые идеи или идеи для других разработчиков.
Предположим, вы используете JS-фреймворк, который поддерживает функциональность "push state", а ваш backend-фреймворк - Ruby on Rails. У вас простой блог-сайт, и вы хотите, чтобы поисковые системы индексировали все ваши статьи
index
иshow
страницы.Допустим, у вас настроены следующие маршруты:
Убедитесь, что каждый контроллер на стороне сервера отображает тот же шаблон, который требуется для запуска вашей клиентской платформы (html / css / javascript / и т. Д.). Если ни один из контроллеров не соответствует в запросе (в этом примере у нас есть только набор действий RESTful для
ArticlesController
), тогда просто сопоставьте что-нибудь еще и просто визуализируйте шаблон и позвольте клиентской платформе обрабатывать маршрутизацию. Единственная разница между попаданием в контроллер и совпадением с подстановочными знаками заключается в возможности отображать контент на основе URL-адреса, который был запрошен на устройства с отключенным JavaScript.Насколько я понимаю, отображать контент, невидимый для браузеров, - плохая идея. Поэтому, когда Google его индексирует, люди проходят через Google, чтобы посетить заданную страницу, и там нет никакого контента, тогда вы, вероятно, будете наказаны. На ум приходит то, что вы визуализируете контент в
div
узле, который вы используетеdisplay: none
в CSS.Однако я почти уверен, что это не имеет значения, если вы просто сделаете это:
А затем с помощью JavaScript, который не запускается, когда устройство с отключенным JavaScript открывает страницу:
Таким образом, для Google и для всех, у кого устройства с отключенным JavaScript, они увидят необработанный / статический контент. Итак, содержание является физически там и будет видна всем пользователям с устройствами JavaScript-инвалидов.
Но, когда пользователь посещает той же странице и на самом деле имеет JavaScript,
#no-js
узел будет удален, чтобы не загромождать ваше приложение. Затем ваша клиентская среда будет обрабатывать запрос через маршрутизатор и отображать то, что пользователь должен видеть, когда включен JavaScript.Я думаю, что это действенный и довольно простой способ использования. Хотя это может зависеть от сложности вашего веб-сайта / приложения.
Хотя, пожалуйста, поправьте меня, если это не так. Просто подумал, что поделюсь своими мыслями.
источник
Используйте NodeJS на стороне сервера, просматривайте свой клиентский код и маршрутизируйте URI каждого http-запроса (за исключением статических ресурсов http) через серверный клиент, чтобы предоставить первый bootnap (снимок страницы, на которой он находится). Используйте что-то вроде jsdom для обработки dom-ops jquery на сервере. После возврата bootnap настройте соединение через веб-сокет. Вероятно, лучше всего различать клиент websocket и клиент на стороне сервера, создав некое соединение оболочки на стороне клиента (клиент на стороне сервера может напрямую связываться с сервером). Я работал над чем-то вроде этого: https://github.com/jvanveen/rnet/
источник
Используйте Google Closure Template для рендеринга страниц. Он компилируется в javascript или java, поэтому страницу легко отобразить как на стороне клиента, так и на стороне сервера. При первой встрече с каждым клиентом визуализируйте html и добавьте javascript в качестве ссылки в заголовке. Сканер будет читать только html, но браузер выполнит ваш скрипт. Все последующие запросы из браузера могут быть выполнены через API, чтобы минимизировать трафик.
источник