Что нужно знать о сайте на SPA SEO-специалисту

В статье руководитель группы оптимизаторов Webit Мария Ефимова рассказывает, что такое SPA-сайты, как их определить, и зачем нужен пререндеринг.

1. Что такое SPA-сайты

SPA (single page application) – одностраничное приложение. Из названия понятно, что это сайт, состоящий из 1 страницы – index.html.

Примеры сайтов на SPA:

Чтобы понять, чем отличается SPA от обычного сайта, необходимо посмотреть на то, как они работают в сравнении.

На обычном сайте пользователь получает HTML-разметку с сервера, она оформляется с помощью стилей из полученных CSS-файлов, а затем накладываются JS-скрипты которые «оживляют» интерактивные части сайта. При переходе на другую страницу с сервера снова получается HTML и всё происходит заново. Это если совсем упростить то, как работает обычный сайт.

Принцип работы классического SPA немного отличается. При первичном посещении сайта пользователь не получает никакой HTML-разметки, вместо этого он получает один или несколько JS-файлов, которые уже содержат в себе весь необходимый HTML и иногда CSS код. Параллельно с этим делается запрос к серверу, чтобы получить динамические данные (контент).

После того как файлы получены, JavaScript формирует HTML-разметку прямо в браузере пользователя и накладывает необходимый CSS для оформления. Именно поэтому если открыть исходный код классического SPA, вы не увидите там ничего кроме подключения JS и иногда CSS файлов, потому что весь HTML, который понадобится пользователю, уже лежит внутри JS-файлов.

Например:

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

Такой подход сильно ускоряет переходы между страницами, и за счет этого пользователь может использовать сайт, не дожидаясь момента, когда сервер сформирует HTML и отдаст его, потому что тут этого шага просто нет. Причем разработчики SPA пошли еще дальше и научили JS-код подгружать другие необходимые JS-файлы именно тогда, когда они нужны, а не сразу все. Назвали такой процесс lazy-loading.

К сожалению, классическое SPA не очень полезно, если вы хотите продвигать сайт, так как далеко не все поисковые роботы научились правильно интерпретировать JS-код, чтобы индексировать его. По умолчанию роботы видят SPA почти пустым HTML-файлом, в котором нет ничего, кроме подключения файлов. Но и тут разработчики нашли выход. Называется он «пререндеринг».

2. Какие SPA-сайты бывают

Существуют различные фреймворки для разработки SPA-приложений. Самые популярные:

  • Angular
  • React (библиотека)
  • Vue
  • Ember и др.

Фреймворк – это программное обеспечение, которое облегчает и ускоряет разработку проекта. Фреймворк диктует правила разработки программного продукта и построения его архитектуры, задавая некий «каркас», который нужно будет расширять и изменять согласно указанным требованиям.

Далее будем рассматривать SPA-сайты на фреймворке Angular.

3. Как определить, что сайт является SPA на Angular

Для этого необходимо будет открыть консоль разработчика во вкладке с исследуемым сайтом (ctrl shift i).

Консоль разработчика в браузере Яндекс

Для исследования SPA-сайта потребуются вкладки:

  • Network,
  • Elements.

Существует несколько способов определить, что сайт построен с помощью фреймворка Angular.

  • По коду

В исходном коде страницы (ctrl shift i) во вкладке Elements присутствует тег с атрибутом ng-version.

Данный тег добавляется самим Ангуляром при компиляции приложения и указывает на версию фреймворка. На данный момент последней версией Angular является версия 11.

  • Бандлы (файлы js)

Bundling – объединение всех файлов JS-приложения в несколько больших с целью минимизации количества запросов к серверу.

Во вкладке Network загружаются JS-скрипты: main.js, runtime.js, scripts.js, polyfills.js. Названия основных бандлов не меняются в Angular. (Тем не менее, не стоит забывать, что в других фреймворках разработчики сами могут задать аналогичные названия файлов).

Важно! Если в названиях JS-файлов нет хэш-кода (main.*.js, где * – произвольный набор букв и цифр, которые указывают на использование прод-билд), то на сайте не используется AOT-компиляция (про AOT-компиляцию читайте в разделе «На что обратить внимание в консоли разработчика?»).

  • С помощью плагина браузера, позволяющего определить CMS, фреймворк, язык программирования и др.

Например, Wappalyzer.

4. На что обратить внимание в консоли разработчика

Для улучшения производительности SPA-приложения разработчик может применить несколько способов оптимизации, которые можно проверить в консоли:

  • Минификация (Minification) – это удаление из кода пустых строк, комментариев, неиспользованного кода (tree shaking – встряхивание дерева). За счет этого уменьшается размер бандлов. В минифицированном файле будет 1–2 строки, тогда как в неминифицированном – много.
Минифицированный бандл main.js
  • Аглификация (Uglify) – это замена длинных названий элементов (методов, переменных и др.) на короткие, при этом размер файла будет меньше. Как правило, используется вместе с минификацией.
  • Сжатие. Сжатие ответов является стандартной практикой уменьшения используемого трафика для загрузки приложения. Указав заголовок Accept-Encoding в запросе, браузер говорит серверу, какие алгоритмы сжатия он поддерживает на клиентском компьютере. В свою очередь, сервер в заголовке ответа устанавливает значение для Content-Encoding, чтобы сообщить браузеру, какой алгоритм сжатия был применен.

Для проверки необходимо посмотреть заголовки ответа (Response headers) – есть ли Content-Encoding и какое значение содержит (например, gzip).

Помимо этого, можно проверить, как реализована архивация – для всех файлов или только для тяжелых. Легкие респонсы (по 1–2 КБ) не должны архивироваться, т.к. распаковка занимает время. Соблюдение этой рекомендации не очень критично, т.к. не дает ощутимый прирост по производительности.

  • AOT (в ангуляре) – ahead of time – предварительная компиляция – при переходе по урлу какие-то кусочки кода сформированы заранее. Это дает ощутимый прирост в скорости загрузки сайта. Еще есть JIT-компиляция (Just in time – компиляция прямо в браузере).

Производительность SPA-приложения зависит от размера передаваемой информации. Именно поэтому из года в год Angular от версии к версии борется за уменьшение размера бандлов (js-файлов).

При JIT-компиляции в бандлы кладется compiler, который, во-первых, занимает дополнительное место, а во-вторых, отбирает ресурсы клиента на компиляцию шаблонов (html-кода). При AOT-компиляции HTML переводится в JS функции, а compiler не включается в бандлы. Таким образом размер бандла уменьшается, а скорость компиляции шаблонов увеличивается, т.к. уже проделана предварительная компиляция.

  • Lazyloading модули. Эта технология позволяет приложению грузиться кусочками, а не единым js-ником загружать весь сайт. Проверить, есть ли lazyloading можно при переходах по сайту с открытой консолью разработчика (вкладка Network). Если грузятся дополнительные файлы JS, то lazyloading присутствует. Ангуляр рекомендует разбивать JS на кусочки и грузить их только тогда, когда пользователь к ним обращается.

Структуру SPA-проекта можно представить в виде дерева: от ствола идут множество веток (модулей). Каждый модуль должен подгружаться по мере использования. В случае, когда грузится все дерево целиком, скорость первоначальной загрузки сайта падает, что негативно сказывается на всех метриках.

  • Утечки памяти: подписки (subscribe), методы. Компоненты приложения общаются между собой через подписки. Некоторые разработчики забывают чистить за собой подписки, и они нагружают память клиента. Подписки должны очищаться. Оставленные подписки влияют на загрузку и скорость приложения во время работы с ним (при переходах по страницам приложение требует много памяти устройства и грузится ощутимо дольше). Проверить можно во вкладке Memory в консоли, используя запись профиля Allocation Sampling:

После начала записи необходимо переходить по страницам сайта с открытой консолью разработчика. Не обязательно делать это долго. После остановки записи будет сформирован лог:

Столбец Total Size информирует о передаваемых данных на клиент. На скриншоте видно, что некоторые функции сайта передали ОЧЕНЬ много данных, которые забивают оперативную память устройства. Таким образом, на мобильных устройствах продолжительное использование сайта может приводить к проблемам с производительностью.

  • Версия Angular – с девятой версии технология Ivy включена по умолчанию. Ivy – технология по компиляции и рендерингу. Является прорывной технологией, т.к. в некоторых случаях позволяет сократить размеры бандлов до 40%, что положительно сказывается на первоначальной загрузке сайта.

Проверить версию Angular в консоли разработчика можно по значению параметра ng-version:

Если указана версия 8, то можно спросить у разработчиков, включена ли технология Ivy.

  • URL routing. Каждая страница сайта должна иметь свой URL-адрес (routing). По заданному URL должна формироваться конкретная страница с необходимым контентом. Важно проверить, формируются ли отдельные URL для страниц: корзина, фильтрации по товарам, сортировки, результаты поиска по сайту и др.

При этом на SPA-сайтах есть модули, которые не должны иметь свой routing, например, модальные окна форм, вкладки.

5. Пререндеринг

Что это и зачем?

Рендеринг – это генерация статичных страниц, которые содержат DOM (Document Object Model – дерево тегов HTML).

Пререндеринг – это сформированные кусочки DOM или всей страницы целиком на стороне сервера.

Преимущества:

  • ускоряет отрисовку страницы на клиенте, т.к. пользователю отправляется уже заранее сформированный ответ (response);
  • не требует дополнительных запросов к серверу;
  • уменьшает время до интерактивности страницы;
  • формирует страницу для индексации роботами поисковых систем.

Какой бывает?

Рендеринг документа (построение DOM) может происходить на сервере (SSR – server Side Rendering) и на клиенте (Client Side Rendering), т.е. в браузере.

Для SEO нас интересует вариант SSR, при котором страницы на сервере уже сформированы заранее в HTML-копии и отдаются роботам поисковых систем максимально быстро. Таким образом, при обращении робота (определяется по user-агенту) к серверу, response по соответствующему запросу (URL) уже готов заранее. Это позволит ускорить первоначальную загрузку страницы и уменьшить время ответа сервера.

Варианта SSR, при котором HTML-копия формируется на сервере при запросе, лучше избегать, т.к. в данном случае время ответа сервера будет большое (серверу нужно время на рендеринг HTML-страницы). Однако при статическом SSR важно поддерживать актуальность сохраненных HTML-копий страниц на сервере.

У Angular пререндеринг для SEO на стороне сервера реализован с помощью технологии Universal. Уточнить, как у приложения реализован SSR, можно у разработчиков.

Как проверить, есть ли рендеринг на стороне сервера

Можно воспользоваться консолью разработчика:

1. Открыть вкладку Network conditions. Она находится в дополнительных опциях (More tools).

2. Выбрать User-agent Googlebot.

3. Указать галочку Disable Cache (игнорировать кеш).

4. Обновить страницу.

5. Проверить содержимое вкладки Response у исследуемой страницы:

На что обратить внимание

1. Не все элементы страницы могут быть включены в рендеринг статичной копии HTML. Для проверки наличия элемента страницы в копии для ботов поисковых систем можно использовать поиск Ctrl F, сравнивания содержимое Response под ботом и вкладки Elements (отрендеренной страницы браузером).

2. Верстка некоторых элементов может отличаться от воспроизводимых с ними действий. Например, элемент может быть кликабельным и перенаправлять пользователя на другую страницу, но в HTML-копии не будет указан тег < a >:

На скриншоте пример, где ссылка из карточки товара в SSR-копии для гуглбота выводится тегом < div >.

3. В коде HTML-копии могут выводиться лишние элементы. Для проверки кода можно скопировать содержимое Response и проанализировать в блокноте.

6. Настройка счетчиков аналитики

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

Для SPA-сайтов требуется установка и настройка специальных счетчиков. Хелпы:

Проверить корректность данных в счетчиках аналитики можно (очень приблизительно) по статистике вебмастеров (Яндекс.Вебмастер – Статистика поисковых запросов), сравнивая с данными счетчиков:

  • данные Яндекс.Вебмастер;
  • данные Яндекс.Метрики;
  • данные Google Analitycs для Яндекс (сеансы).

Если имеется разница более чем в 30% между Метрикой, GA и Вебмастером, то, возможно, счетчики настроены некорректно, и часть визитов не фиксируется или попадает в другой источник.

0
9 комментариев
Написать комментарий...
В А

Статья о том, что нужно знать о сайте на SPA SEO-специалисту, но мы расскажем вам о другом. Так получилось)

Ответить
Развернуть ветку
Digital-агентство Webit
Автор

Мы ставили своей целью раскрыть те аспекты, которые не освещаются широко и обычно опускаются в статьях про SPA. Если вам не хватило какой-то конкретной информации - задавайте вопросы и мы с удовольствием их осветим.

Ответить
Развернуть ветку
Милана Шахова

Хорошая статья, по делу)
Отдельный лайк за установку счетчиков для SPA-сайтов, думаю, это полезный совет для тех, кто впервые с ними сталкивается.

Ответить
Развернуть ветку
Лилия Вежеватова

Большое спасибо за подробный разбор. 

Ответить
Развернуть ветку
Digital-агентство Webit
Автор

Лилия, спасибо за вашу обратную связь!

Ответить
Развернуть ветку
Виктор Петров

Полезненько, в закладки.

Ответить
Развернуть ветку
Digital-агентство Webit
Автор

Рады, что наш материал оказался вам полезен)

Ответить
Развернуть ветку
Евгений Сухоруков

Ясно.

Ответить
Развернуть ветку
Reset Button

Самый лучший вариант проверить "есть ли рендеринг на стороне сервера", использовать серчконсоль, так как от фейковых гуглоботов  частенько стоит защита.

Ответить
Развернуть ветку
6 комментариев
Раскрывать всегда