Подтвердить что ты не робот

AngularJS SEO для статических веб-страниц (S3 CDN)

Я искал способы улучшить SEO для приложений angularJS, размещенных на CDN, таких как Amazon S3 (т.е. простое хранилище без бэкэнд). Большинство решений там, PhantomJS, prerender.io, seo.js и т.д., полагайтесь на бэкэнд для распознавания URL-адреса ?_escaped_fragment_, который генерирует искатель, а затем извлекает соответствующую страницу из другого места. Даже grunt-html-snapshot в конечном итоге вам нужно это сделать, даже если вы заранее создадите страницы моментальных снимков.

Это решение в основном опирается на использование cloudflare в качестве обратного прокси-сервера, что кажется немного ненужным, учитывая, что большая часть устройства безопасности и т.д., что их служба обеспечивает полностью избыточную для статического сайта. Настройка обратного прокси-сервера сама по себе, как предложено здесь, также кажется проблематичной, учитывая, что для нее потребуется либо i) маршрутизация всех приложений AngularJS, в которых мне нужен статический html для одного прокси-сервера, который потенциально hamper performance или ii) создание отдельного прокси-сервера для каждого приложения, после чего я могу настроить бэкэнд, который не является доступным в масштабе, в котором я работаю.

В любом случае, или статически размещенные приложения AngularJS с отличным SEO в принципе невозможны, пока Google не обновит их сканеры?


Отправлено на webmasters после комментариев Джона Конде.

4b9b3361

Ответ 1

Вот полный обзор того, как сделать ваше приложение оптимизированным для SEO в сервисе хранения, таком как S3, с хорошими URL-адресами (нет #) и все с хрюканьем с простой командой, которая будет выполняться после сборки:

grunt seo

Это все еще головоломка обходных решений, но она работает, и это лучшее, что вы можете сделать. Спасибо @ericluwj и его blogpost, которые вдохновили меня.

Обзор

Структура цели и URL

Цель состоит в том, чтобы создать 1 html файл для каждого состояния в вашем приложении angular. Единственное серьезное предположение заключается в том, что вы удаляете "#" из своего URL-адреса, используя html5history (что вы должны делать!) И что все ваши пути являются абсолютными или используют состояния angular. Есть много сообщений, объясняющих, как это сделать.

Урлс заканчивается конечной косой чертой   http://yourdomain.com/page1/

Лично я убедился, что http://yourdomain.com/page1 (без конечной косой черты) также достигает своего адресата, но здесь нет темы. Я также убедился, что каждый язык имеет другое состояние и другой URL-адрес.

Логика SEO

Наша цель состоит в том, что когда кто-то достигает вашего веб-сайта с помощью http-запроса:

  • Если это поисковый робот: держите его на странице, содержащей требуемый html. Страница также содержит логику angular (например, для запуска вашего приложения), но искатель не может прочитать, что он намеренно застрял с html, который вы ему обслуживали, и проиндексирует это.
  • Для нормальных людей и интеллектуальных машин: убедитесь, что angular активирован, удалите сгенерированный html и запустите приложение обычно

Задачи grunt

Здесь мы идем с заданиями:

  //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
  ]);

Шаг 1: Запустите локальный сервер с одновременным: seo

Сначала нам нужно запустить локальный сервер (например, службу grunt), чтобы мы могли делать снимки нашего веб-сайта.

//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
  ]
}

Шаг 2. Создание моментального снимка вашего сайта с помощью grunt prerender

Плагины grunt-prerender позволяют делать снимок любого веб-сайта с помощью PhantomJS. В нашем случае мы хотим сделать снимок всех страниц сайта localhost, который мы только что запустили.

//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 
  }
}

Шаг 3: Очистите беспорядок с заменой grunt

Если вы откроете предварительно обработанные файлы, они будут работать для сканеров, но не для людей. Для людей, использующих хром, ваши директивы будут загружаться дважды. Поэтому вам необходимо перенаправить интеллектуальные браузеры на домашнюю страницу до активации angular (т.е. Сразу после головы).

//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: ''} 
    ]
  }

Также убедитесь, что у вас есть этот код в вашем index.html в элементе ui-view, который очищает все сгенерированные директивы html до начала angular.

<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>

Шаг 4: загрузка в aws

Сначала загрузите свою папку dist, которая содержит вашу сборку. Затем вы перезаписываете его с файлами, которые вы предварительно загрузили и обновили.

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},
    ]
  }
}

Что это, у вас есть свое решение! Оба человека и боты смогут прочитать ваше веб-приложение

Ответ 2

Если вы используете ng-cloak интересными способами, может быть хорошее решение.

Я не пробовал это сам, но он должен работать в теории

Решение сильно зависит от CSS, но оно должно отлично. Например, у вас есть три состояния в вашем приложении angular: - index (путь: #/) - about (путь: #/about) - контакт (путь: #/контакт)

Базовый регистр для индекса также может быть добавлен, но будет сложным, поэтому я оставлю его сейчас.

Сделайте так, чтобы ваш HTML выглядел следующим образом:

<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>

(Важно, чтобы вы поместили свой индексный код последним, если хотите сделать его более удивительным)

Далее Сделайте ваш CSS похожим на это: -

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

Только это, вероятно, будет достаточно хорошо для вас. Директива mg-cloak сохраняет ваше приложение angular скрытым, если angular не загружается и вместо этого отображает ваш статический контент. Google получит ваш статический контент в HTML. В качестве бонусных конечных пользователей также можно увидеть статический контент стиля стилей при загрузке angular.

Затем вы можете стать более креативными, если начнете использовать: целевые псевдоселектора в вашем CSS. Вы можете использовать фактические ссылки в своем статическом контенте, но просто привяжите их к различным идентификаторам. Поэтому в #index div убедитесь, что у вас есть ссылки на #about и #contact. Обратите внимание на отсутствие "/" в ссылках. Идентификатор HTML не может начинаться с косой черты.

Затем сделайте так, чтобы ваш CSS выглядел следующим образом:

[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;}

Теперь у вас есть полноценное статическое приложение WITH ROUTINg, которое работает до запуска angular.

В качестве дополнительного бонуса, когда запускается angular, он достаточно умен, чтобы автоматически конвертировать #about в #/, и опыт даже не должен прерываться.

Кроме того, чтобы не забыть, что проблема SEO полностью решена, конечно. Я еще не использовал эту технику, так как у меня всегда был сервер для настройки, но мне очень интересно, как это работает для вас.

Надеюсь, что это поможет.

Ответ 3

На самом деле это очень трудная задача, но мне удалось заставить SEO работать с моим сайтом AngularJS SPA (размещенным на AWS S3) в http://www.jobbies.co/. Основная идея состоит в том, чтобы предварительно сгенерировать и заполнить содержимое в HTML. Шаблоны будут по-прежнему загружаться, когда страница загружается, а предварительно обработанный контент будет заменен.

Вы можете узнать больше о моем решении в http://www.ericluwj.com/2015/11/17/seo-for-angularjs-on-s3.html, но обратите внимание, что существует множество условий.

Ответ 4

Поскольку AWS предлагает Lambda @Edge в качестве сервиса, мы можем справиться с этой проблемой без ворчания или чего-то еще. (По крайней мере для основных вещей)

Я пробовал Lambda @Edge, и он работал, как ожидалось, в моем случае у меня были все маршруты, установленные в "/" в Lambda @Edge (кроме файлов, присутствующих в s3, таких как css, изображения и т.д.).

Событием для лямбда, которое я установил, является "viewerRequest", а следующий код.

'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);
};

Журналы в облачном канале очень трудно проверить, поскольку журналы заполняются в области облачного экрана, которая ближе к граничному местоположению, которое обрабатывает запрос.

Например, Хотя эта Лямбда развернута/написана для нас - восток, я вижу это в регионе юг-юг, когда я обращаюсь к облачному офису из Сингапура. Проверьте его в инструментах Google для веб-мастеров Google "Получить как Google", и страница будет отображена и просмотрена как ожидалось.

Ответ 5

Я искал несколько дней, чтобы найти решение для этого. Насколько я знаю, это не очень хорошее решение проблемы. Я надеюсь, что firebase в конечном итоге позволит перенаправлять пользователя-агента. Если у вас есть деньги, вы можете использовать предприятие MaxCDN. Они предлагают пограничные правила, которые включают переадресацию с помощью пользовательского агента.

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