Embora o número 2 possa ser "mais fácil" para você como desenvolvedor, ele fornece apenas o rastreamento do mecanismo de pesquisa. E sim, se o Google descobrir que você exibe conteúdo diferente, você poderá ser penalizado (não sou especialista nisso, mas já ouvi falar disso).
Tanto o SEO quanto a acessibilidade (não apenas para pessoas com deficiência, mas a acessibilidade por meio de dispositivos móveis, dispositivos com tela sensível ao toque e outras plataformas não padronizadas para computação / Internet) têm uma filosofia subjacente semelhante: marcação semanticamente rica que é "acessível" (ou seja, pode acessados, visualizados, lidos, processados ou usados) em todos esses navegadores diferentes. Um leitor de tela, um rastreador de mecanismo de pesquisa ou um usuário com JavaScript habilitado devem ser capazes de usar / indexar / entender a funcionalidade principal do seu site sem problemas.
pushState
não aumenta esse fardo, na minha experiência. Ele apenas traz o que costumava ser uma reflexão tardia e "se tivermos tempo" para a vanguarda do desenvolvimento da web.
O que você descreve na opção nº 1 geralmente é o melhor caminho a percorrer - mas, como outros problemas de acessibilidade e SEO, fazer isso pushState
em um aplicativo pesado em JavaScript requer planejamento antecipado ou isso se tornará um fardo significativo. Ele deve ser inserido na arquitetura da página e do aplicativo desde o início - a atualização é dolorosa e causará mais duplicação do que o necessário.
Eu tenho trabalhado pushState
recentemente com o SEO em algumas aplicações diferentes e achei o que considero uma boa abordagem. Ele segue basicamente o item nº 1, mas é responsável por não duplicar html / templates.
A maioria das informações pode ser encontrada nessas duas postagens no blog:
http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
e
http://lostechies.com/derickbailey/2011/06/22/rendering-a-rails-partial-as-a-jquery-template/
O essencial disso é que eu uso modelos ERB ou HAML (executando Ruby on Rails, Sinatra etc.) para renderizar no lado do servidor e criar os modelos do lado do cliente que o Backbone pode usar, bem como para minhas especificações JavaScript do Jasmine. Isso elimina a duplicação da marcação entre o lado do servidor e o lado do cliente.
A partir daí, é necessário executar algumas etapas adicionais para que seu JavaScript funcione com o HTML renderizado pelo servidor - verdadeiro aprimoramento progressivo; pegando a marcação semântica que foi entregue e aprimorando-a com JavaScript.
Por exemplo, estou criando um aplicativo de galeria de imagens com pushState
. Se você solicitar /images/1
do servidor, ele renderizará toda a galeria de imagens no servidor e enviará todo o HTML, CSS e JavaScript para o seu navegador. Se você tiver o JavaScript desativado, ele funcionará perfeitamente. Todas as ações que você executar solicitarão um URL diferente do servidor e o servidor renderizará toda a marcação para o seu navegador. Se você tiver o JavaScript ativado, ele pegará o HTML já renderizado junto com algumas variáveis geradas pelo servidor e assumirá o controle a partir daí.
Aqui está um exemplo:
<form id="foo">
Name: <input id="name"><button id="say">Say My Name!</button>
</form>
Depois que o servidor renderiza isso, o JavaScript o seleciona (usando uma visualização Backbone.js neste exemplo)
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")
});
});
Este é um exemplo muito simples, mas acho que é o ponto principal.
Quando instante a exibição após o carregamento da página, estou fornecendo o conteúdo existente do formulário que foi renderizado pelo servidor para a instância da exibição como el
a exibição. Estou não chamar prestar ou ter a visão de gerar uma el
para mim, quando a primeira vista é carregado. Eu tenho um método de renderização disponível para depois que a exibição estiver em execução e a página estiver toda em JavaScript. Isso me permite renderizar novamente a exibição mais tarde, se necessário.
Clicar no botão "Diga meu nome" com o JavaScript ativado fará com que uma caixa de alerta. Sem JavaScript, ele seria postado de volta no servidor e o servidor poderia renderizar o nome para um elemento html em algum lugar.
Editar
Considere um exemplo mais complexo, em que você tem uma lista que precisa ser anexada (dos comentários abaixo)
Digamos que você tenha uma lista de usuários em uma <ul>
tag. Essa lista foi renderizada pelo servidor quando o navegador fez uma solicitação e o resultado se parece com:
<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>
Agora você precisa percorrer esta lista e anexar uma visualização e modelo de Backbone a cada um dos <li>
itens. Com o uso do data-id
atributo, você pode encontrar o modelo de onde cada tag vem facilmente. Você precisará de uma visualização de coleção e de itens que seja inteligente o suficiente para se conectar a esse 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();
Neste exemplo, o UserListView
loop percorrerá todas as <li>
tags e anexará um objeto de visualização com o modelo correto para cada uma. ele configura um manipulador de eventos para o evento de alteração de nome do modelo e atualiza o texto exibido do elemento quando ocorre uma alteração.
Esse tipo de processo, para pegar o html que o servidor renderizou e fazer com que meu JavaScript o controle e execute, é uma ótima maneira de fazer as coisas rolarem para SEO, acessibilidade e pushState
suporte.
Espero que ajude.
Eu acho que você precisa disso: http://code.google.com/web/ajaxcrawling/
Você também pode instalar um back-end especial que "renderiza" sua página executando javascript no servidor e, em seguida, o exibe no Google.
Combine as duas coisas e você terá uma solução sem programar as coisas duas vezes. Desde que seu aplicativo seja totalmente controlável por meio de fragmentos de âncora.)
fonte
Então, parece que a principal preocupação é estar SECO
<a href="https://stackoverflow.com/someotherpage">mylink</a>
, o servidor reescreve o URL do arquivo do aplicativo, carrega-o no phantom.js e o html resultante é enviado ao bot, e assim por diante. ..<a>
tags. Nesse caso, o tratamento 404 é mais fácil, pois você pode simplesmente verificar a existência do arquivo estático com um nome que contenha o caminho da URL.Aqui estão alguns exemplos usando o phantom.js para seo:
http://backbonetutorials.com/seo-for-single-page-apps/
http://thedigitalself.com/blog/seo-and-javascript-with-phantomjs-server-side-rendering
fonte
Se você estiver usando o Rails, tente poirot . É uma jóia que simplifica a reutilização do bigode ou do guidão modelos de lado do cliente e do servidor.
Crie um arquivo em suas visualizações como
_some_thingy.html.mustache
.Renderizar lado do servidor:
Coloque o modelo na cabeça para uso do lado do cliente:
Rendre do lado do cliente:
fonte
Para adotar um ângulo um pouco diferente, sua segunda solução seria a correta em termos de acessibilidade ... você forneceria conteúdo alternativo para usuários que não podem usar javascript (aqueles com leitores de tela etc.).
Isso adicionaria automaticamente os benefícios do SEO e, na minha opinião, não seria visto como uma técnica "impertinente" pelo Google.
fonte
Interessante. Tenho procurado soluções viáveis, mas isso parece bastante problemático.
Na verdade, eu estava mais inclinado para a sua segunda abordagem:
Aqui está minha opinião sobre como resolver o problema. Embora não esteja confirmado para o trabalho, ele pode fornecer algumas idéias ou idéias para outros desenvolvedores.
Suponha que você esteja usando uma estrutura JS que suporta a funcionalidade "push state", e sua estrutura de back-end é Ruby on Rails. Você tem um site de blog simples e deseja que os mecanismos de pesquisa indexem todo o seu artigo
index
eshow
páginas.Digamos que você tenha suas rotas configuradas assim:
Assegure-se de que todo controlador do lado do servidor renderize o mesmo modelo que sua estrutura do lado do cliente exige para ser executado (html / css / javascript / etc). Se nenhum dos controladores for correspondido na solicitação (neste exemplo, temos apenas um conjunto de ações RESTful para o
ArticlesController
), basta corresponder a qualquer outra coisa, renderizar o modelo e deixar que a estrutura do lado do cliente lide com o roteamento. A única diferença entre acertar um controlador e acertar o correspondente curinga seria a capacidade de renderizar o conteúdo com base na URL que foi solicitada aos dispositivos com JavaScript desativado.Pelo que entendi, é uma má idéia renderizar conteúdo que não é visível para os navegadores. Então, quando o Google indexa, as pessoas acessam o Google para visitar uma determinada página e não há conteúdo, então você provavelmente será penalizado. O que vem à mente é que você processa o conteúdo em um
div
nódisplay: none
em CSS.No entanto, tenho certeza de que não importa se você simplesmente faz isso:
E, em seguida, usando JavaScript, que não é executado quando um dispositivo desabilitado para JavaScript abre a página:
Dessa forma, para o Google e para qualquer pessoa com dispositivos desabilitados para JavaScript, eles veriam o conteúdo bruto / estático. Portanto, o conteúdo está fisicamente lá e é visível para qualquer pessoa com dispositivos desabilitados para JavaScript.
Mas, quando um usuário visita a mesma página e realmente tem o JavaScript ativado, o
#no-js
nó será removido para não bagunçar seu aplicativo. Em seguida, sua estrutura do lado do cliente manipulará a solicitação através do roteador e exibirá o que um usuário deve ver quando o JavaScript estiver ativado.Eu acho que essa pode ser uma técnica válida e bastante fácil de usar. Embora isso possa depender da complexidade do seu site / aplicativo.
Embora, por favor, corrija-me se não for. Apenas pensei em compartilhar meus pensamentos.
fonte
Use o NodeJS no lado do servidor, navegue no código do lado do cliente e roteie cada uri da solicitação http (exceto recursos http estáticos) através de um cliente no lado do servidor para fornecer o primeiro 'bootsnap' (um instantâneo da página em que está o estado). Use algo como jsdom para lidar com jquery dom-ops no servidor. Após o bootnap retornar, configure a conexão do websocket. Provavelmente, é melhor diferenciar entre um cliente de websocket e um cliente do servidor, estabelecendo algum tipo de conexão de wrapper no cliente (o cliente do servidor pode se comunicar diretamente com o servidor). Estou trabalhando em algo assim: https://github.com/jvanveen/rnet/
fonte
Use o Google Closure Template para renderizar páginas. Ele é compilado em javascript ou java, por isso é fácil renderizar a página no lado do cliente ou do servidor. No primeiro encontro com todos os clientes, renderize o html e adicione javascript como link no cabeçalho. O rastreador lerá apenas o html, mas o navegador executará seu script. Todas as solicitações subsequentes do navegador podem ser feitas na API para minimizar o tráfego.
fonte