Vue.js и SEO: как оптимизировать реактивные сайты для поисковых систем и ботов
Индексируются ли сайты, созданные с помощью реактивных фреймворков, Google и другими поисковыми системами? Обязательно ли настраивать предварительный рендеринг, как советуют SEO-консультанты? Или они не правы?
Реактивные JavaScript — фреймворки (такие как React, Vue.js и Angular) в последнее время стали очень популярны, и неудивительно, что они используются во все большем количестве веб-сайтов и приложений благодаря их гибкости, модульности и простоте автоматизированного тестирования.
Эти фреймворки позволяют достигать новых, ранее немыслимых вещей на веб-сайте или в приложении, но как они работают с точки зрения SEO? Индексирует ли Google страницы, созданные с помощью этих фреймворков?
В этой статье я расскажу в основном о Vue.js, так как этот фреймворк я использовал чаще всего, и с которым у меня есть непосредственный опыт в плане индексации поисковыми системами, но я могу предположить, что большинство то, что я расскажу, действительно и для других платформ.
Немного предыстории проблемы
Как работает индексация
Чтобы ваш веб-сайт был проиндексирован Google, его должен сканировать Googlebot (программное обеспечение для автоматической индексации, которое посещает ваш веб-сайт и сохраняет содержимое страниц в его индексе) по ссылкам на каждой странице. Робот Googlebot также ищет специальные XML-файлы Sitemap на веб-сайте для поиска страниц, которые могут быть неправильно связаны с вашим сайтом, и для получения дополнительной информации (например о том, как часто меняются страницы на веб-сайте и когда они в последний раз менялись).
Немного истории
Еще несколько лет назад (до 2009 года) Google индексировал только HTML-код веб-сайта. Общеизвестным SEO правилом было то, что важные ссылки и контент не должны быть созданы с помощью JavaScript, поскольку они не будут проиндексированы Google, и это так же может повлечь за собой штрафы для веб-сайта, потому что Google может посчитать это «поддельным контентом», как если бы владелец сайта пытался показать пользователям что-то отличное от того, что было показано поисковым системам.
Мошенники часто помещали много HTML-контента, оптимизированного для SEO, а прятали его от реальных пользователей с помощью JavaScript. Google всегда предостерегал от этой практики:
«Предоставление роботу Google другого контента, который отображается пользователю, считается маскировкой и противоречит нашим правилам для веб-мастеров (Webmaster Guidelines)».
Вы можете быть оштрафованы за это. В некоторых случаях вас могут оштрафовать за предоставление разного контента разным пользовательским агентам на стороне сервера, а также за переключение контента через JavaScript после загрузки страницы. Я думаю, что это показывает нам, что Google в действительности распознавал контент созданный JavaScript — по крайней мере, для сравнения окончательного HTML сайта (после выполнения JavaScript) и необработанного HTML, который он анализировал для своих индексов. Но Googlebot не выполнял JavaScript все время, и Google не использовал сгенерированный JavaScript контент для целей индексации.
Затем, учитывая возросшее использование AJAX для отображения динамического контента на веб-сайтах, Google предложила «схему сканирования AJAX» (AJAX crawling scheme), чтобы помочь пользователям индексировать веб-сайты на основе AJAX. Но это было очень сложно в реализации; по сути, веб-сайт требовал рендеринга страниц с включенным содержанием AJAX. По запросу Google сервер должен был предоставит версию страницы со всем (или большей частью) контентом, который был бы сгенерирован динамически с помощью JavaScript, включенного в HTML-страницу — предварительно визуализированной как HTML-снимок контента. Этот процесс предоставления сервером контента, который предназначался для создания на стороне клиента, подразумевал, что тем, кто хочет создать сайт, который в значительной степени полагается на JavaScript, и при этом индексировался в Google, приходилось проходить через множество технических проблем.
Например, если содержимое, прочитанное AJAX, поступило из внешней веб-службы, необходимо было дублировать те же вызовы веб-службы на стороне сервера и создать на стороне сервера тот же HTML, который был бы создан на стороне клиента. Это было очень сложно в реализации, потому что до появления Node.js требовалось, по крайней мере, частично дублировать одну и ту же логику рендеринга в двух разных языках программирования: JavaScript для фронтенд интерфейса и PHP, Java, Python, Ruby и т. д. для бэкэнд. Это называется «рендеринг на стороне сервера» (server-side rendering), и это может привести к очень сложно архитектуре: если вы внесли важные изменения в способ рендеринга контента на фронтенде, вам придется дублировать эти изменения на бэкэнде.
Единственная альтернатива, позволяющая избежать дублирования логики, заключалась в том, чтобы рендерить свой сайт с помощью браузера, выполняющего JavaScript, и сохранять конечные результаты на своем сервере а затем передовать их Googlebot. Это похоже на то, что сейчас называется «предварительный рендеринг» (pre-rendering).
Google (с его схемой сканирования AJAX) также гарантировал, что вы избежите штрафов из-за того, что в этом случае вы предоставляете разный контент роботу Googlebot и пользователю. Но с 2015 года Google не рекомендует использовать AJAX crawling scheme и на официального сайте в блоге (official blog post), написано:
«Сегодня, если вы не запрещаете работу Googlebot он будет сканировать JavaScript или CSS, и он способен распознавать веб-страницы, так же как современные браузеры».
Это говорит нам не о том, что Googlebot внезапно приобрел возможность выполнения JavaScript при индексации веб-страниц, поскольку мы знаем, что он делал это в течение очень долгого времени (по крайней мере, для проверки поддельного контента и мошенничества). Вместо этого нам сообщили, что результат выполнения JavaScript будет проиндексирован и использован в поисковой выдаче.
Похоже, это означает, что нам больше не нужно беспокоиться о том, чтобы предоставить Google HTML-код на стороне сервера. Однако мы видим существование и развитие множество инструментов для рендеринга на стороне сервера и предварительного рендеринга, доступных для фреймворков. Кроме того, при работе с SEO-агентствами над крупными проектами предварительный рендеринг представляется обязательным. Почему так происходит?
Как Google на самом деле индексирует страницы, созданные с помощью фреймворков?
Эксперимент
Чтобы увидеть, как Google на самом деле индексирует веб-сайты, созданных с помощью фреймворков, я провел небольшой эксперимент. Я создал небольшой сайт с Vue.js и по-разному отобразил разные части текста.
Содержание сайта взято из описания книги Infinite Jest Дэвида Фостера Уоллеса в Infinite Jest Wiki. Есть пара вводных текстов для всей книги и список персонажей с их индивидуальной биографией. Какой контент я разместил на сайте:
- Разместил текст в статическом HTML за пределами основного контейнера Vue.js;
- Разместил текст, который визуализируется немедленно после запуска Vue.js, так как он содержится в переменных, которые уже присутствуют в коде приложения: определил его в объекте data;
- Разместил текст, который визуализируется Vue.js из объекта data, но с задержкой 300 мс;
- Биографии персонажей я загрузил с помощью REST API, который я специально создал с помощью Sandbox. Поскольку я предполагал, что Google выполнит код веб-сайта и через некоторое время остановится, чтобы сделать снимок текущего состояния страницы, я настроил каждый url возрастающую задержку: первая с 0 мс, вторая с 300 мс, третий с 600 мс и так далее до 2700 мс.
Каждая биография персонажа была сокращена и содержала ссылку на подстраницу, которая доступна только через Vue.js (URL генерируются Vue.js с использованием API истории), но не на стороне сервера (если вызвать URL-адрес страницы на прямую, то будет ответ 404). Я это сделал, чтобы проверить, будут ли они тоже проиндексированы. Хотя я сразу предположил, что они не будут проиндексированы, поскольку они не являются правильными ссылками, которые отображаются на стороне сервера, и Google никак не сможет направить пользователей на эти ссылки напрямую. Просто я хотел проверить этот момент.
Я опубликовал этот небольшой тестовый сайт на своей странице Github и попросил Google его проиндексировать — взгляните.
Результат
Результаты эксперимента оказались следующими:
- Содержимое, находящееся в статическом HTML-контенте, хорошо индексируется Google (что довольно очевидно);
- Содержимое, генерируемое Vue в режиме реального времени, так же всегда индексируется Google;
- Содержимое, которое генерируется Vue, но отображается через 300 мс, так же индексируется;
- Содержимое получаемое через веб-сервис с некоторой задержкой иногда проиндексировалось а иногда нет. Я проверял индексацию страницы Google в разные моменты, и контент, который был вставлен последним (через пару секунд), иногда индексируется, а иногда нет. Контент, который отображается довольно быстро, в большинстве случаев индексируется, даже если он поступает от асинхронного вызова внешней веб-службы. Это зависит от наличия у Google бюджета рендеринга для каждой страницы и сайта, который зависит от его внутренних алгоритмов, и может сильно отличаться в зависимости от рейтинга вашего сайта и текущего состояния очереди рендеринга Googlebot. Таким образом, вы не можете полагаться на контент, поступающий от внешних веб-сервисов, для индексации;
- Подстраницы (так как они не доступны в виде прямой ссылки) не индексируются.
Что этот эксперимент говорит нам? По сути, Google индексирует динамически генерируемый контент, даже если он поступает из внешнего веб-сервиса, но не гарантируется, что контент будет проиндексирован, если он «поступит слишком поздно». У меня был подобный опыт с другими реальными, производственными веб-сайтами помимо этого эксперимента.
Конкурентный SEO
Итак, контент индексируется, но что этот эксперимент не говорит нам: будет ли контент ранжироваться на конкурентной основе? Будет ли Google предпочитать сайт со статическим содержанием динамически генерируемому сайту? Это не простой вопрос.
Исходя из моего опыта, я могу сказать, что динамически генерируемый контент может занимать верхние позиции в поисковой выдаче. Я работал над сайтом для новой модели крупной автомобильной компании, запустил новый сайт с новым доменом третьего уровня. Сайт был полностью создан с помощью Vue.js — с очень небольшим содержанием в статическом HTML, кроме <title> тегов и meta описаний.
Сайт начал ранжировать по низко-частотным запросам в первые несколько дней после публикации, и текстовые фрагменты в поисковой выдаче содержали слова, поступающие непосредственно из динамического контента.
В течение трех месяцев он занял первое место по большинству поисковых запросов, связанных с этой моделью автомобиля, что было относительно легко сделать, поскольку он размещался на официальном домене, принадлежащем производителю автомобиля, и домен был в значительной степени связан с авторитетными веб-сайтами.
Мы вынуждены были опубликовать сайт без предварительной визуализации (pre-rendering) из-за сжатых сроков и нехватки времени, отведенного на проект.
Анимированный текст
То, что Google точно не индексирует, это сильно анимированный текст. Сайт одной из компаний, с которой я работаю, Rabbit Hole Consulting, содержит множество текстовых анимаций, которые выполняются, пока пользователь выполняет прокрутку.
Основные тексты на главной странице сайта не предназначены для индексации поисковыми системами, поскольку они не оптимизированы для SEO. Они не используют ключевые слова: они предназначены только для сопровождения пользователя в концептуальном путешествии по компании. Текст вставляется динамически, когда пользователь входит в различные разделы сайта.
Ни один из текстов в этих разделах сайта не индексируется Google. Чтобы Google показывал что-то значимое в результатах поиска, мы добавили статический текст в нижний колонтитул (футер сайта) под контактной формой, и этот контент стал отображаться как часть содержимого страницы в результатах поиска.
Текст в нижнем колонтитуле (футоре) индексируется и отображается в поисковой выдаче, даже если он не виден пользователям сразу после загрузки страницы. Это подтверждает мое мнение о том, что контент индексируется, даже если он не отображается сразу для пользователя, а отображается в HTML через какое то время после длительной задержки.
Предварительный рендеринг (pre-rendering)?
Итак, почему столько суеты по поводу предварительного рендеринга — будь то на стороне сервера или во время компиляции проекта? Это действительно необходимо? Хотя некоторые фреймворки, такие как Nuxt, значительно упрощают его создание, это все равно нелегкое дело, поэтому выбор, использовать его или нет, не является простым.
Я думаю, что в принципе в общем случае его использование не обязательно. Но его использование будет обязательным требованием, если большая часть контента, который вы хотите проиндексировать в Google, поступает из внешнего веб-сервиса и не доступна сразу во время рендеринга, а в некоторых случаях может быть недоступна вообще из-за, например, времени простоя веб-службы. Если во время посещений Googlebot часть вашего контента поступает слишком медленно, он не будет проиндексирован.
Кроме того, у меня нет доказательств различий ранжирования между статическим контентом и динамически генерируемым контентом. Это может потребовать еще один эксперимент. Я думаю, что весьма вероятно, что если контент поступает из внешней веб-службы и загружается не сразу, это может повлиять на восприятие Google эффективности вашего сайта, что является очень важным фактором для ранжирования.
Рекомендуемое чтение: How Mobile Web Design Affects Local Search (And What To Do About It)
Другие соображения
Совместимость
До недавнего времени Googlebot использовал довольно старую версию Chromium (проект с открытым исходным кодом, на котором основан Google Chrome), а именно версию 41. Это означало, что некоторые недавние функции JavaScript или CSS не могли корректно отображаться Google (например, IntersectionObserver, Синтаксис ES6 и т.д.).
Google недавно объявил, что теперь он запускает последнюю версию Chromium (74, на момент написания) в Googlebot, и что эта версия будет регулярно обновляться. Тот факт, что Google использовал Chromium 41, могло иметь большое значение для сайтов, которые решили не учитывать совместимость с IE11 и другими старыми браузерами.
Ошибки Javascript
Если вы полагаетесь на то, что Googlebot выполняет ваш JavaScript для визуализации жизненно важного контента, то следует избегать серьезных ошибок JavaScript, которые могут помешать отображению контента. Хотя боты могут анализировать и индексировать HTML, который не совсем корректен (хотя всегда желательно иметь действительный HTML на любом сайте!), если есть ошибка JavaScript, препятствующая загрузке некоторого контента, Google не сможет проиндексировать этот контент.
В любом случае, если вы полагаетесь на JavaScript для предоставления жизненно важного контента вашим пользователям, то, скорее всего, у вас должны быть обширные модульные тесты для проверки любых возможных ошибок блокировки. Имейте в виду, однако, что ошибки могут возникать и при непредсказуемых сценариев, например, в случае неправильной обработки ошибок в ответах API.
Лучше иметь какое-то программное обеспечение для проверки ошибок в реальном времени (например, Sentry или LogRocket), которое будет предупреждать вас о любых ошибках, которые вы можете и не обнаружить во время модульного или ручного тестирования.
Другие поисковые движки
Другие поисковые системы не работают так же хорошо, как Google с динамическим контентом. Похоже, что Bing вообще не индексирует динамический контент, как и DuckDuckGo или Baidu. Вероятно, этим поисковым системам не хватает ресурсов и вычислительных мощностей, которыми обладает Google.
Разбор страницы в браузере без заголовка и выполнение JavaScript в течение нескольких секунд для анализа отображаемого содержимого, безусловно, требует больше ресурсов, чем простое чтение HTML. Или, может быть, эти поисковые системы решили не сканировать динамический контент по некоторым другим причинам. Независимо от причины, если ваш проект должен поддерживать любую из этих поисковых систем, вам нужно настроить предварительный рендеринг.
Другие боты
Помните, что на ваш сайт будут заходить и другие боты. Наиболее важными примерами являются Twitter, Facebook и другие боты социальных сетей, которым необходимо получать метаинформацию о ваших страницах, чтобы показать предварительный просмотр вашей страницы, когда она связана с их пользователями. Эти боты не будут индексировать динамическое содержимое, а будут отображать только метаинформацию, найденную в статическом HTML.
Подстраницы
Если ваш сайт представляет собой так называемый «одностраничный веб-сайт», и весь соответствующий контент расположен на одной странице HTML, у вас не возникнет проблем с индексированием этого контента в Google. Однако если вам нужно, чтобы Google проиндексировал и отобразил какую-либо дополнительную страницу на веб-сайте, вам все равно нужно будет создать статический HTML-код для каждого из них — даже если вы используете JavaScript фрейворк для проверки текущего URL-адреса и предоставления соответствующего содержимого для размещения на этой странице. В этом случае мой совет — создавать серверные (или статические) страницы.
Заключение
При исследовании этой статьи я пришел к следующим выводам:
- Если вы ориентируетесь только на Google, не обязательно использовать предварительный рендеринг для полной индексации вашего сайта:
- Вы не должны полагаться на сторонние веб-службы для получения контента, который необходимо проиндексировать, особенно если они не всегда отвечают быстро.
- Содержимое, которое вы вставляете в HTML-код, через визуализацию Vue.js индексируется, но вы не должны использовать анимированный текст или текст, который вставляется в DOM после каких либо действий пользователя (например прокрутка и т. п.)
- Убедитесь, что вы проверяете ошибки JavaScript, так как они могут привести к тому, что целые страницы или разделы не будут проиндексированы или ваш сайт вообще не будет проиндексирован.
- Если на вашем сайте есть несколько страниц, вам все равно нужно иметь некоторую логику для создания страниц, которая используют туже систему рендеринга, что и домашняя страница, для того что бы Google мог их проиндексировать как отдельные URL-адреса.
- Если вам нужно иметь разные описания и изображения при предварительном просмотре для социальных сетей на разных страницах, вам нужно будет решить эту проблему либо на стороне сервера, либо путем компиляции статических страниц для каждого URL.
- Если вам нужен ваш сайт для работы в поисковых системах, отличных от Google, вам определенно понадобится какой-то предварительный рендеринг.
Оригинальная статья: Paolo Mioni Vue.js And SEO: How To Optimize Reactive Websites For Search Engines And Bots