tutorial software instalar guide create javascript angularjs amazon-web-services amazon-s3 seo

javascript - software - instalar angularjs



AngularJS SEO para páginas web estáticas(S3 CDN) (5)

Aquí hay una descripción completa de cómo hacer que su aplicación sea amigable con el SEO en un servicio de almacenamiento como S3, con lindas URL (no #) y todo con gruñido con el comando simple que se realizará después de la compilación:

grunt seo

Todavía es un rompecabezas de soluciones, pero está funcionando y es lo mejor que puedes hacer. Gracias a @ericluwj y su blog que me inspiró.

Visión de conjunto

La estructura del objetivo y la URL

El objetivo es crear 1 archivo html por estado en su aplicación angular. La única suposición importante es que elimines el ''#'' de tu url usando html5history (¡lo cual deberías hacer!) Y que todos tus caminos son absolutos o usan estados angulares. Hay muchas publicaciones que explican cómo hacerlo.

Las URL terminan con una barra inclinada como esta http://yourdomain.com/page1/

Personalmente, me aseguré de que http://yourdomain.com/page1 ( sin barra diagonal) también llegue a su destino, pero eso está fuera de tema aquí. También me aseguré de que cada idioma tenga un estado diferente y una URL diferente.

La lógica de SEO

Nuestro objetivo es que cuando alguien llegue a su sitio web a través de una solicitud http:

  • Si es un rastreador de motor de búsqueda: mantenlo en la página que contiene el html requerido. La página también contiene lógica angular (por ejemplo, para iniciar su aplicación) pero el rastreador no puede leer eso, por lo que intencionalmente se quedará atrapado con el html que le sirvió y lo indexará.
  • Para humanos normales y máquinas inteligentes: asegúrese de que angular se active, borre el html generado e inicie su aplicación normalmente

Las tareas roncas

Aquí vamos con las tareas grupales:

//grunt plugins you will need: grunt.loadNpmTasks(''grunt-prerender''); grunt.loadNpmTasks(''grunt-replace''); grunt.loadNpmTasks(''grunt-wait''); grunt.loadNpmTasks(''grunt-aws-s3''); //The grunt tasks in the right order grunt.registerTask(''seo'', ''First launch server, then prerender and replace'', function (target) { grunt.task.run([ ''concurrent:seo'' //Step 1: in parrallel launch server, then perform so-called seotasks ]); }); grunt.registerTask(''seotasks'', [ ''http'', //This is an API call to get all pages on my website. Skipping this step in this tutorial. ''wait'', // wait 1.5 sec to make sure that server is launched ''prerender'', //Step 2: create a snapshot of your website ''replace'', //Step 3: clean the mess ''sitemap'', //Create a sitemap of your production environment ''aws_s3:dev'' //Step 4: upload ]);

Paso 1: Inicie el servidor local con concurrente: seo

Primero tenemos que lanzar un servidor local (como el servicio de grunt) para que podamos tomar instantáneas de nuestro sitio web.

//grunt config concurrent: { seo: [ ''connect:dist:keepalive'', //Launching a server and keeping it alive ''seotasks'' //now that we have a running server we can launch the SEO tasks ] }

Paso 2: crea una instantánea de tu sitio web con grunt prerender

Los plugins grunt-prerender te permiten tomar una instantánea de cualquier sitio web usando PhantomJS. En nuestro caso, queremos tomar una instantánea de todas las páginas del sitio web localhost que acabamos de lanzar.

//grunt config prerender: { options: { sitePath: ''http://localhost:9001'', //points to the url of the server you just launched. You can also make it point to your production website. //As you can see the source urls allow for multiple languages provided you have different states for different languages (see note below for that) urls: [''/'', ''/projects/'', ''/portal/'',''/en/'', ''/projects/en/'', ''/portal/en/'',''/fr/'', ''/projects/fr/'', ''/portal/fr/''],//this var can be dynamically updated, which is done in my case in the callback of the http task hashed: true, dest: ''dist/SEO/'',//where your static html files will be stored timeout:5000, interval:5000, //taking a snapshot of how the page looks like after 5 seconds. phantomScript:''basic'', limit:7 //# pages processed simultaneously } }

Paso 3: Limpia el desorden con el reemplazo del gruñido

Si abre los archivos prestados, funcionarán para los rastreadores, pero no para los humanos. Para los humanos que usan Chrome, sus directivas se cargarán dos veces. Por lo tanto, debe redirigir los navegadores inteligentes a su página de inicio antes de que se active el angular (es decir, justo después de la cabeza).

//Add the script tag to redirect if we''re not a search bot replace: { dist: { options: { patterns: [ { match: ''<head>'', //redirect to a clean page if not a bot (to your index.html at the root basically). replacement: ''<head><script>if(!/bot|googlebot|crawler|spider|robot|crawling/i.test(navigator.userAgent)) { document.location = "/#" + window.location.pathname; }</script>'' //note: your hashbang (#) will still work. } ], usePrefix: false }, files: [ {expand: true, flatten: false, src: [''dist/SEO/*/**/*.html''], dest: ''''} ] }

También asegúrese de tener este código en su index.html en su elemento ui-view, que borra todas las directivas html generadas ANTES de que angular comienza.

<div ui-view autoscroll="true" id="ui-view"></div> <!-- this script is needed to clear ui-view BEFORE angular starts to remove the static html that has been generated for search engines who cannot read angular --> <script> if(!/bot|googlebot|crawler|spider|robot|crawling/i.test( navigator.userAgent)) { document.getElementById(''ui-view'').innerHTML = ""; } </script>

Paso 4: Cargar a Aws

Primero carga su carpeta dist que contiene su compilación. Luego lo sobreescribes con los archivos que entregaste y actualizaste.

aws_s3: { options: { accessKeyId: "<%= aws.accessKeyId %>", // Use the variables secretAccessKey: "<%= aws.secret %>", // You can also use env variables region: ''eu-west-1'', uploadConcurrency: 5, // 5 simultaneous uploads }, dev: { options: { bucket: ''xxxxxxxx'' }, files: [ {expand: true, cwd: ''dist/'', src: [''**''], exclude: ''SEO/**'', dest: '''', differential: true}, {expand: true, cwd: ''dist/SEO/'', src: [''**''], dest: '''', differential: true}, ] } }

¡Eso es, tienes tu solución! Tanto humanos como bots podrán leer tu aplicación web

He estado buscando formas de mejorar SEO para aplicaciones angularJS alojadas en un CDN como Amazon S3 (es decir, almacenamiento simple sin back-end). La mayoría de las soluciones que existen, PhantomJS , prerender.io , seo.js , etc., se basan en un back-end para reconocer la ?_escaped_fragment_ que genera el rastreador y luego obtener la página relevante de otro lado. Incluso grunt-html-snapshot finalmente necesita que haga esto, aunque genere las páginas instantáneas con anticipación.

Esta solution se basa básicamente en el uso de cloudflare como un proxy inverso, lo que parece un desperdicio dado que la mayoría de los dispositivos de seguridad, etc. que su servicio proporciona, son totalmente redundantes para un sitio estático. La configuración de un proxy inverso como se sugiere here también parece problemático, ya que requeriría i) enrutar todas las aplicaciones de AngularJS Necesito estáticas html a través de un servidor proxy que podría obstaculizar el rendimiento o ii) configurar un servidor proxy independiente para cada aplicación , en ese punto también puedo configurar un backend, que no es asequible en la escala en la que estoy trabajando.

¿Hay alguna forma de hacerlo, o las aplicaciones AngularJS alojadas estáticamente con un gran SEO son básicamente imposibles hasta que Google actualice sus rastreadores?

Reubicado en webmasters siguiendo los comentarios de John Conde.


Como AWS está ofreciendo Lambda @ Edge como un servicio, podemos manejar este problema sin gruñir ni nada más. (Al menos para cosas básicas)

Probé Lambda @ Edge y funcionó como se esperaba, en mi caso acabo de tener todas las rutas establecidas en "/" en Lambda @ Edge (Excepto por los archivos que están presentes en s3 como css, imágenes, etc.).

El evento para el Lambda que establecí es "viewerRequest" y el siguiente es el código.

''use strict''; exports.handler = (event, context, callback) => { console.log("Event received is", JSON.stringify(event)); console.log("Context received is", context); const request = event.Records[0].cf.request; if (request.uri.endsWith(".rt")) { console.log("URI is matching with .rt, the URI is ", request.uri); request.uri = "/"; } else { console.log("URI is not ending with rt so letting it go URI is", request.uri); } console.log("Final request URI is", request.uri); callback(null, request); };

Los registros en el reloj en la nube son poco difíciles de verificar ya que los registros se llenan en la región del reloj en la nube que está más cerca de la ubicación del borde que está manejando la solicitud.

Por ej. Aunque este Lambda se implementa / escribe para nosotros, al este, veo esto en la región ap-sur, ya que estoy accediendo a la nube desde Singapur. Lo revisó en las herramientas Google webmaster ''Fetch as google'' y la página se muestra y visualiza como se esperaba.


En realidad, esta es una tarea que de hecho es muy problemática, pero he logrado que el SEO funcione bien con mi sitio AngularJS SPA (alojado en AWS S3) en http://www.jobbies.co/ . La idea principal es pregenerar y poblar el contenido en el HTML. Las plantillas se seguirán cargando cuando se cargue la página y se reemplazará el contenido preprocesado.

Puede leer más sobre mi solución en http://www.ericluwj.com/2015/11/17/seo-for-angularjs-on-s3.html , pero tenga en cuenta que hay muchas condiciones.


He estado buscando días para encontrar una solución para esto. Hasta donde sé, no hay una buena solución para el problema. Espero que firebase eventualmente habilite las redirecciones de usuario-agente. Si tiene el dinero, podría usar la empresa MaxCDN. Ofrecen reglas perimetrales que incluyen redireccionamientos por agente de usuario.

https://www.maxcdn.com/features/rules/


si usas ng-cloak de maneras interesantes, podría haber una buena solución.

No lo he intentado yo mismo, pero debería funcionar en teoría

La solución depende mucho de CSS, pero debería funcionar perfectamente. Por ejemplo, tiene tres estados en su aplicación angular: - índice (nombre de ruta: # /) - sobre (ruta de acceso: # / sobre) - contacto (ruta de acceso: # / contacto)

También se puede agregar el caso base para el índice, pero será complicado, así que lo dejaré de lado por el momento.

Haga que su HTML se vea así:

<body> <div ng-app="myApp" ng-cloak> <!-- Your whole angular app goes here... --> </div> <div class="static"> <div id="about class="static-other"> <!-- Your whole about content here... --> </div> <div id="contact" class="static-other"> <!-- Your whole contact content here... --> </div> <div id="index" class="static-main"> <!-- Your whole index content here... --> </div> </div> </body>

(Es importante que ponga su caso índice al final, si quiere hacerlo más increíble)

Siguiente Haz que tu CSS se vea algo como esto: -

[ng-cloak], .static { display: none; } [ng-cloak] ~ .static { display: block; }

Simplemente eso probablemente funcionará lo suficientemente bien para ti de todos modos. La directiva mg-cloak mantendrá su aplicación angular oculta cuando angular no está cargada y mostrará su contenido estático en su lugar. Google obtendrá su contenido estático en el HTML. Como beneficio adicional, los usuarios finales también pueden ver bien estilos de contenido estático mientras cargas angulares.

A continuación, puede ser más creativo si comienza a utilizar: pseudo selectores de destino en su CSS. Puede usar enlaces reales en su contenido estático, pero solo haga enlaces a varios identificadores. Entonces, en #index div, asegúrese de tener enlaces a #about y #contact. Tenga en cuenta que falta ''/'' en los enlaces. Los ID de HTML no pueden comenzar con una barra inclinada.

Luego haz que tu CSS se vea así:

[ng-cloak], .static { display: none; } [ng-cloak] ~ .static { display: block; } .static-other {display: none;} .static-other:target {display: block;} .static-other:target ~ .static-main {display: none;}

Ahora tiene una aplicación estática completamente funcional CON ROUTINg que funciona antes de la puesta en marcha angular.

Como una ventaja adicional, cuando angular se inicia es lo suficientemente inteligente como para convertir #about a # / about automáticamente, y la experiencia ni siquiera debería romperse.

Además, no hay que olvidar que el problema de SEO se ha resuelto por completo, por supuesto. Todavía no he usado esta técnica, ya que siempre he tenido que configurar un servidor, pero estoy muy interesado en cómo funciona esto para usted.

Espero que esto ayude.