Eu tenho trabalhado em como tornar um SPA rastreável pelo Google com base nas instruções do Google . Embora existam algumas explicações gerais, não consegui encontrar em nenhum lugar um tutorial passo a passo mais completo com exemplos reais. Depois de terminar isso, eu gostaria de compartilhar minha solução para que outras pessoas também possam usá-la e possivelmente melhorá-la ainda mais.
Estou usando MVC
com Webapi
controladores e Phantomjs no lado do servidor e Durandal no lado do cliente com push-state
ativado; Também uso Breezejs para interação de dados cliente-servidor, todos os quais recomendo vivamente, mas tentarei dar uma explicação geral o suficiente que também ajudará as pessoas que usam outras plataformas.
143
Respostas:
Antes de começar, entenda o que o Google exige , principalmente o uso de URLs bonitos e feios . Agora vamos ver a implementação:
Lado do Cliente
No lado do cliente, você possui apenas uma única página html que interage dinamicamente com o servidor por meio de chamadas AJAX. é disso que se trata o SPA. Todas as
a
tags no lado do cliente são criadas dinamicamente no meu aplicativo. Mais adiante, veremos como tornar esses links visíveis ao bot do google no servidor. Cada uma dessasa
tags precisa ter umpretty URL
nahref
tag para que o bot do Google o rastreie. Você não deseja que ahref
peça seja usada quando o cliente clicar nela (mesmo que você queira que o servidor possa analisá-la, veremos isso mais tarde), porque talvez não desejemos que uma nova página seja carregada, apenas para fazer uma chamada AJAX, exibindo alguns dados em parte da página e alterar o URL via javascript (por exemplo, usando HTML5pushstate
ou comDurandaljs
). Então, nós temos umhref
atributo para o google, bem como sobreonclick
qual faz o trabalho quando o usuário clica no link. Agora, como eupush-state
não quero usar nenhum#
URL, umaa
tag típica pode ficar assim:<a href="http://www.xyz.com/#!/category/subCategory/product111" onClick="loadProduct('category','subCategory','product111')>see product111...</a>
'category' e 'subCategory' provavelmente seriam outras frases, como 'comunicação' e 'telefones' ou 'computadores' e 'laptops' para uma loja de eletrodomésticos. Obviamente, haveria muitas categorias e subcategorias diferentes. Como você pode ver, o link é diretamente para a categoria, subcategoria e produto, não como parâmetros extras para uma página específica da "loja", como
http://www.xyz.com/store/category/subCategory/product111
. Isso ocorre porque eu prefiro links mais curtos e simples. Isso implica que não haverá uma categoria com o mesmo nome que uma das minhas 'páginas', ou seja, 'Não vou entrar em como carregar os dados via AJAX (a
onclick
parte), pesquisá-los no google, há muitas boas explicações. A única coisa importante aqui que quero mencionar é que, quando o usuário clica neste link, quero que o URL no navegador fique assim:http://www.xyz.com/category/subCategory/product111
. E este URL não é enviado para o servidor! lembre-se, este é um SPA onde toda a interação entre o cliente e o servidor é feita via AJAX, sem links! todas as 'páginas' são implementadas no lado do cliente e o URL diferente não faz uma chamada para o servidor (o servidor precisa saber como lidar com esses URLs caso sejam usados como links externos de outro site para o site, veremos isso mais tarde na parte do servidor). Agora, isso é tratado maravilhosamente por Durandal. Eu recomendo fortemente, mas você também pode pular esta parte se preferir outras tecnologias. Se você escolher, e também estiver usando o MS Visual Studio Express 2012 para Web como eu, poderá instalar o Durandal Starter Kit e, em seguidashell.js
, usar algo como isto:Há algumas coisas importantes a serem observadas aqui:
route:''
) é para a URL que não possui dados extras, ou sejahttp://www.xyz.com
. Nesta página, você carrega dados gerais usando o AJAX. Na verdade, pode não havera
tags nesta página. Você vai querer adicionar a seguinte tag de modo bot que o Google vai saber o que fazer com ele:<meta name="fragment" content="!">
. Essa tag fará o bot do google transformar o URL para owww.xyz.com?_escaped_fragment_=
qual veremos mais adiante.mapUnknownRoutes
entra. Ele mapeia essas rotas desconhecidas para a rota 'store' e também remove qualquer '!' do URL, caso sejapretty URL
gerado pelo mecanismo de pesquisa do Google. A rota 'store' pega as informações na propriedade 'fragment' e faz a chamada AJAX para obter os dados, exibi-los e alterar o URL localmente. No meu aplicativo, não carrego uma página diferente para cada chamada; Apenas altero a parte da página em que esses dados são relevantes e também altero o URL localmente.pushState:true
que instrui Durandal a usar URLs de estado de envio.É tudo o que precisamos no lado do cliente. Ele pode ser implementado também com URLs com hash (em Durandal, você simplesmente remove o
pushState:true
para isso). A parte mais complexa (pelo menos para mim ...) foi a parte do servidor:Lado do servidor
Estou usando
MVC 4.5
no lado do servidor comWebAPI
controladores. O servidor realmente precisa lidar com três tipos de URLs: os gerados pelo google - ambospretty
eugly
também um URL 'simples' com o mesmo formato que o que aparece no navegador do cliente. Vamos ver como fazer isso:URLs bonitas e 'simples' são primeiro interpretadas pelo servidor como se tentassem fazer referência a um controlador inexistente. O servidor vê algo parecido
http://www.xyz.com/category/subCategory/product111
e procura um controlador chamado 'categoria'. Entãoweb.config
, adiciono a seguinte linha para redirecioná-las para um controlador de tratamento de erros específico:Agora, isso transforma o URL para algo como:
http://www.xyz.com/Error?aspxerrorpath=/category/subCategory/product111
. Quero que a URL seja enviada ao cliente que carregará os dados via AJAX, portanto, o truque aqui é chamar o controlador 'index' padrão como se não estivesse fazendo referência a nenhum controlador; Eu faço isso adicionando um hash ao URL antes de todos os parâmetros 'category' e 'subCategory'; o URL do hash não requer nenhum controlador especial, exceto o controlador 'index' padrão e os dados são enviados ao cliente, que remove o hash e usa as informações após o hash para carregar os dados via AJAX. Aqui está o código do controlador do manipulador de erros:Mas e os URLs feios ? Eles são criados pelo bot do Google e devem retornar HTML simples que contém todos os dados que o usuário vê no navegador. Para isso eu uso phantomjs . O Phantom é um navegador sem cabeça que faz o que o navegador está fazendo no lado do cliente - mas no lado do servidor. Em outras palavras, o phantom sabe (entre outras coisas) como obter uma página da Web por meio de uma URL, analisá-la, incluindo a execução de todo o código javascript (e também a obtenção de dados por chamadas AJAX) e devolver o HTML que reflete o DOM. Se você estiver usando o MS Visual Studio Express, muitos desejam instalar o phantom através deste link .
Mas primeiro, quando uma URL feia é enviada para o servidor, precisamos capturá-la; Para isso, adicionei à pasta 'App_start' o seguinte arquivo:
Isso é chamado de 'filterConfig.cs' também em 'App_start':
Como você pode ver, 'AjaxCrawlableAttribute' roteia URLs feias para um controlador chamado 'HtmlSnapshot' e aqui está este controlador:
O associado
view
é muito simples, apenas uma linha de código:@Html.Raw( ViewBag.result )
Como você pode ver no controlador, o phantom carrega um arquivo javascript chamado
createSnapshot.js
em uma pasta que criei chamadaseo
. Aqui está este arquivo javascript:Em primeiro lugar, quero agradecer a Thomas Davis pela página em que obtive o código básico de :-).
Você notará algo estranho aqui: o fantasma continua recarregando a página até mais. Se isso não acontecer dentro de 10 segundos, desisto (levará apenas um segundo para o máximo). O HTML retornado contém todos os links que o usuário vê no navegador. O script não funcionará corretamente porque as tags existentes no instantâneo HTML não fazem referência ao URL correto. Isso também pode ser alterado no arquivo fantasma javascript, mas não acho necessário, porque o snapshort HTML é usado apenas pelo google para obter os links e não para executar o javascript; esses links
checkLoaded()
função retorne verdadeira. Por que é que? isso ocorre porque meu SPA específico faz várias chamadas AJAX para obter todos os dados e colocá-los no DOM na minha página, e o phantom não pode saber quando todas as chamadas foram concluídas antes de retornar o reflexo HTML do DOM. O que fiz aqui é após a chamada final do AJAX, adiciono um<span id='compositionComplete'></span>
, para que, se essa tag existir, eu saiba que o DOM está concluído. Eu faço isso em resposta aocompositionComplete
evento de Durandal , veja aqui<script>
a
fazem referência a um URL bonito e, se for o caso, se você tentar ver o instantâneo HTML em um navegador, você receberá erros de javascript, mas todos os links funcionarão corretamente e direcionarão você ao servidor mais uma vez com um URL bonito dessa vez obtendo a página totalmente funcional.É isso. Agora, o servidor sabe como lidar com URLs bonitas e feias, com o estado push ativado no servidor e no cliente. Todos os URLs feios são tratados da mesma maneira usando o phantom; portanto, não há necessidade de criar um controlador separado para cada tipo de chamada.
Uma coisa que você pode preferir a mudança não é para fazer a chamada uma 'categoria / subcategoria / produto' geral, mas para adicionar um 'loja' para que o link será algo parecido com:
http://www.xyz.com/store/category/subCategory/product111
. Isso evitará o problema na minha solução de que todos os URLs inválidos são tratados como se fossem realmente chamadas para o controlador 'index', e suponho que eles possam ser tratados no controlador 'store' sem a adiçãoweb.config
mostrada acima. .fonte
O Google agora pode renderizar páginas de SPA: descontinuando nosso esquema de rastreamento AJAX
fonte
Aqui está um link para uma gravação de screencast da minha aula de treinamento do Ember.js que hospedei em Londres em 14 de agosto. Ele descreve uma estratégia para o aplicativo do lado do cliente e para o aplicativo do servidor, além de demonstrar ao vivo como a implementação desses recursos fornecerá ao seu aplicativo de página única JavaScript uma degradação suave, mesmo para usuários com o JavaScript desativado. .
Ele usa o PhantomJS para ajudar no rastreamento do seu site.
Em resumo, as etapas necessárias são:
Depois que essa etapa estiver concluída, cabe ao seu back-end veicular a versão estática do seu HTML como parte da tag noscript dessa página. Isso permitirá que o Google e outros mecanismos de pesquisa rastreiem todas as páginas do seu site, mesmo que seu aplicativo seja originalmente um aplicativo de página única.
Link para o screencast com os detalhes completos:
http://www.devcasts.io/p/spas-phantomjs-and-seo/#
fonte
Você pode usar ou criar seu próprio serviço para pré-renderizar seu SPA com o serviço chamado pré-renderizador. Você pode conferir no site prerender.io e no projeto do github (ele usa o PhantomJS e o seu site é renderizado).
É muito fácil começar. Você só precisa redirecionar solicitações de rastreadores para o serviço e eles receberão o html renderizado.
fonte
Você pode usar http://sparender.com/, que permite que os aplicativos de página única sejam rastreados corretamente.
fonte