Chociaż punkt 2 może być „łatwiejszy” dla Ciebie jako programisty, zapewnia jedynie indeksowanie w wyszukiwarkach. I tak, jeśli Google dowie się, że obsługujesz różne treści, możesz zostać ukarany (nie jestem w tym ekspertem, ale słyszałem, że tak się dzieje).
Zarówno SEO, jak i dostępność (nie tylko dla osoby niepełnosprawnej, ale także dostępność za pośrednictwem urządzeń mobilnych, urządzeń z ekranem dotykowym i innych niestandardowych platform komputerowych / internetowych) mają podobną filozofię: bogate semantycznie znaczniki, które są „dostępne” (tj. być dostępne, przeglądane, czytane, przetwarzane lub w inny sposób wykorzystywane) do wszystkich tych różnych przeglądarek. Czytnik ekranu, robot wyszukiwarki lub użytkownik z włączoną obsługą JavaScript powinni być w stanie bez problemu korzystać z / indeksować / rozumieć podstawowe funkcje witryny.
pushState
nie dodaje do tego ciężaru, z mojego doświadczenia. Dopiero to, co kiedyś było refleksją i „jeśli mamy czas”, znajduje się na czele tworzenia stron internetowych.
To, co opisujesz w opcji nr 1, jest zwykle najlepszym rozwiązaniem - ale, podobnie jak inne problemy z dostępnością i SEO, zrobienie tego pushState
w aplikacji z dużą ilością JavaScript wymaga planowania z góry lub stanie się znacznym obciążeniem. Powinien on być od początku zapieczętowany w architekturze strony i aplikacji - modernizacja jest bolesna i spowoduje więcej powielania niż jest to konieczne.
pushState
Ostatnio pracowałem z SEO dla kilku różnych aplikacji i znalazłem to, co uważam za dobre podejście. Zasadniczo podąża za Twoim elementem nr 1, ale uwzględnia brak powielania html / templates.
Większość informacji można znaleźć w tych dwóch postach na blogu:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
i
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
Istota tego polega na tym, że używam szablonów ERB lub HAML (z uruchomionym Ruby on Rails, Sinatra itp.) Do renderowania po stronie serwera i do tworzenia szablonów po stronie klienta, których może używać Backbone, a także do specyfikacji Jasmine JavaScript. Eliminuje to powielanie znaczników między stroną serwera i klienta.
Następnie musisz wykonać kilka dodatkowych kroków, aby JavaScript działał z kodem HTML renderowanym przez serwer - prawdziwe ulepszenie progresywne; biorąc dostarczony znacznik semantyczny i ulepszając go o JavaScript.
Na przykład tworzę aplikację galerii obrazów z pushState
. Jeśli zażądasz /images/1
od serwera, wyrenderuje całą galerię obrazów na serwerze i wyśle cały kod HTML, CSS i JavaScript do przeglądarki. Jeśli masz wyłączony JavaScript, będzie działać idealnie. Każda czynność, którą podejmiesz, zażąda innego adresu URL z serwera, a serwer wyrenderuje wszystkie znaczniki dla Twojej przeglądarki. Jeśli jednak masz włączony JavaScript, JavaScript pobierze już wyrenderowany kod HTML wraz z kilkoma zmiennymi wygenerowanymi przez serwer i przejmie stamtąd.
Oto przykład:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Po wyrenderowaniu tego przez serwer, JavaScript powinien to odebrać (używając widoku Backbone.js w tym przykładzie)
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(){
}
});
$(function(){
var model = new MyModel();
var view = new FooView({
model: model,
el: $("#foo")
});
});
To bardzo prosty przykład, ale myślę, że ma sens.
Kiedy instantuję widok po załadowaniu strony, udostępniam istniejącą zawartość formularza, który został wyrenderowany przez serwer, do instancji widoku jako el
dla widoku. Nie wywołuję renderowania ani nie generuję widoku el
, gdy ładowany jest pierwszy widok. Mam dostępną metodę renderowania po uruchomieniu widoku, a cała strona jest w JavaScript. To pozwoli mi później wyrenderować widok, jeśli zajdzie taka potrzeba.
Kliknięcie przycisku „Say My Name” z włączoną obsługą JavaScript spowoduje wyświetlenie okna alertu. Bez JavaScript wysłałby z powrotem na serwer, a serwer mógłby renderować nazwę w jakimś elemencie html.
Edytować
Rozważ bardziej złożony przykład, w którym masz listę, którą należy załączyć (z komentarzy poniżej)
Powiedzmy, że masz listę użytkowników w <ul>
tagu. Ta lista została wyrenderowana przez serwer, gdy przeglądarka wysłała żądanie, a wynik wygląda mniej więcej tak:
<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>
Teraz musisz przejrzeć tę listę i dołączyć widok i model szkieletu do każdego <li>
elementu. Za pomocą data-id
atrybutu można łatwo znaleźć model, z którego pochodzi każdy tag. Będziesz wtedy potrzebował widoku kolekcji i widoku elementów, który jest wystarczająco inteligentny, aby dołączyć się do tego kodu 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();
W tym przykładzie UserListView
pętla przejdzie przez wszystkie <li>
znaczniki i dołączy obiekt widoku z odpowiednim modelem dla każdego z nich. konfiguruje procedurę obsługi zdarzenia dla zdarzenia zmiany nazwy modelu i aktualizuje wyświetlany tekst elementu, gdy następuje zmiana.
Ten rodzaj procesu, polegający na przejęciu kodu HTML renderowanego przez serwer i przejęciu go przez JavaScript, jest świetnym sposobem na rozpoczęcie pracy z SEO, pushState
ułatwieniami dostępu i pomocą techniczną.
Mam nadzieję, że to pomoże.
Myślę, że potrzebujesz tego: http://code.google.com/web/ajaxcrawling/
Możesz także zainstalować specjalny backend, który "renderuje" twoją stronę poprzez uruchomienie javascript na serwerze, a następnie przekazuje go do Google.
Połącz obie rzeczy, a otrzymasz rozwiązanie bez programowania rzeczy dwa razy. (O ile aplikacją można w pełni sterować za pomocą fragmentów kotwicy).
źródło
Wydaje się więc, że głównym problemem jest bycie SUCHYM
<a href="https://stackoverflow.com/someotherpage">mylink</a>
, serwer przepisuje adres URL do pliku aplikacji, ładuje go w phantom.js, a wynikowy kod HTML jest wysyłany do bota i tak dalej. ..<a>
tagi. W tym przypadku obsługa 404 jest łatwiejsza, ponieważ można po prostu sprawdzić, czy istnieje plik statyczny o nazwie zawierającej ścieżkę url.Oto kilka przykładów użycia phantom.js w SEO:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
źródło
Jeśli używasz Railsów, wypróbuj poirot . To klejnot, który sprawia, że ponowne użycie szablonów wąsów lub kierownic po stronie klienta i serwera jest bardzo proste .
Utwórz plik w swoich widokach, takich jak
_some_thingy.html.mustache
.Renderuj po stronie serwera:
<%= render :partial => 'some_thingy', object: my_model %>
Umieść szablon głowy do użytku po stronie klienta:
<%= template_include_tag 'some_thingy' %>
Rendre po stronie klienta:
źródło
Aby spojrzeć z nieco innego punktu widzenia, twoje drugie rozwiązanie byłoby właściwe pod względem dostępności ... Zapewniłbyś alternatywną zawartość użytkownikom, którzy nie mogą używać javascript (ci z czytnikami ekranu itp.).
To automatycznie dodałoby korzyści z SEO i, moim zdaniem, nie byłoby postrzegane jako „niegrzeczna” technika przez Google.
źródło
Ciekawy. Szukałem realnych rozwiązań, ale wydaje się to być dość problematyczne.
Właściwie bardziej skłaniałem się w kierunku twojego drugiego podejścia:
Oto moje podejście do rozwiązania problemu. Chociaż nie potwierdzono, że działa, może dostarczyć pewnych spostrzeżeń lub pomysłów innym programistom.
Załóżmy, że używasz frameworka JS, który obsługuje funkcję „push state”, a twoja struktura zaplecza to Ruby on Rails. Masz prostą witrynę z blogiem i chciałbyś, aby wyszukiwarki indeksowały wszystkie Twoje artykuły
index
ishow
strony.Powiedzmy, że masz skonfigurowane trasy w ten sposób:
resources :articles match "*path", "main#index"
Upewnij się, że każdy kontroler po stronie serwera renderuje ten sam szablon, którego wymaga Twoja struktura po stronie klienta (html / css / javascript / etc). Jeśli żaden z kontrolerów nie jest dopasowany w żądaniu (w tym przykładzie mamy tylko zestaw akcji RESTful dla
ArticlesController
), po prostu dopasuj cokolwiek innego i po prostu wyrenderuj szablon i pozwól strukturze po stronie klienta obsłużyć routing. Jedyną różnicą między uderzeniem w kontroler a trafieniem w dopasowywanie symboli wieloznacznych byłaby możliwość renderowania treści na podstawie adresu URL żądanego na urządzeniach z wyłączoną obsługą JavaScript.Z tego, co rozumiem, renderowanie treści, które nie są widoczne dla przeglądarek, jest złym pomysłem. Więc kiedy Google go indeksuje, ludzie przechodzą przez Google, aby odwiedzić daną stronę i nie ma żadnej treści, wtedy prawdopodobnie zostaniesz ukarany. Przychodzi mi na myśl, że renderujesz zawartość w
div
węźle, który wykonujeszdisplay: none
w CSS.Jestem jednak pewien, że nie ma to znaczenia, jeśli po prostu zrobisz to:
<div id="no-js"> <h1><%= @article.title %></h1> <p><%= @article.description %></p> <p><%= @article.content %></p> </div>
A następnie używając JavaScript, który nie jest uruchamiany, gdy urządzenie z wyłączoną obsługą JavaScript otwiera stronę:
$("#no-js").remove() # jQuery
W ten sposób dla Google i dla każdego, kto ma urządzenia z wyłączoną obsługą JavaScript, zobaczą surową / statyczną zawartość. Tak więc zawartość jest tam fizycznie i jest widoczna dla każdego, kto ma urządzenia z wyłączoną obsługą JavaScript.
Ale gdy użytkownik odwiedza tę samą stronę i faktycznie ma włączoną obsługę JavaScript,
#no-js
węzeł zostanie usunięty, aby nie zaśmiecać aplikacji. Następnie struktura po stronie klienta obsłuży żądanie przez swój router i wyświetli to, co powinien zobaczyć użytkownik, gdy włączony jest JavaScript.Myślę, że może to być poprawna i dość łatwa w użyciu technika. Chociaż może to zależeć od złożoności Twojej witryny / aplikacji.
Chociaż, proszę, popraw mnie, jeśli tak nie jest. Pomyślałem, że podzielę się swoimi przemyśleniami.
źródło
Używaj NodeJS po stronie serwera, przeglądaj kod po stronie klienta i kieruj uri każdego żądania http (z wyjątkiem statycznych zasobów http) przez klienta po stronie serwera, aby zapewnić pierwsze `` bootnap '' (migawkę strony, w której jest). Użyj czegoś takiego jak jsdom do obsługi jquery dom-ops na serwerze. Po zwróceniu sygnału startowego skonfiguruj połączenie WebSocket. Prawdopodobnie najlepiej jest odróżnić klienta sieci Web od klienta po stronie serwera, tworząc po stronie klienta pewnego rodzaju połączenie typu wrapper (klient po stronie serwera może bezpośrednio komunikować się z serwerem). Pracowałem nad czymś takim: https://github.com/jvanveen/rnet/
źródło
Użyj szablonu zamknięcia Google do renderowania stron. Kompiluje się do javascript lub java, więc łatwo jest renderować stronę po stronie klienta lub serwera. Przy pierwszym spotkaniu z każdym klientem wyrenderuj kod HTML i dodaj javascript jako link w nagłówku. Robot odczyta tylko kod HTML, ale przeglądarka wykona skrypt. Wszystkie kolejne żądania z przeglądarki można kierować do interfejsu API, aby zminimalizować ruch.
źródło
To może ci pomóc: https://github.com/sharjeel619/SPA-SEO
Logika
źródło