Берлога Гепарда Быстрее к цели, ещё быстрее
11.08.2022

Переходы по сайту без перезагрузки страниц — устраняем сопутствующие расходы

Переходы по ссылкам без перезагрузки сайта позволяют:

  1. Анимировать переходы, когда блоки сайта “перетекают” в новое состояние.
  2. Загружать информацию только для тех блоков, у которых в новом состоянии, что-то поменялось.

Как следствие, такие переходы:

  1. Повышают удобство работы с сайтом.
  2. Уменьшают нагрузку на сеть.
  3. Повышают скорость работы сайта.

Но это теория. На практике есть нюансы.

Наиболее близкое название для этой технологии — SPA (Single Page Application). С некоторыми уточнениями:

  1. Application, приложение, сайт — всё об одном.
  2. Single Page не значит, что страница одна, просто приложение работает со многими страницами, как с одной. Адрес меняется, а полной перезагрузки не происходит. Переходя на новую страницу с новым адресом, мы, как бы, остаёмся на старой — такая вот игра слов.
  3. Single относится к одной странице и не означает, что приложение централизованное — когда любое состояние знает обо всех других состояниях. SPA-сайт может быть децентрализованным с независимыми друг от друга состояниями.

Сопутствующие расходы

При первом посещении SPA-сайта с переходами без перезагрузки, необходимо загрузить код, который будет осуществлять эти переходы и собирать страницу в браузере. Объём и сложность этого кода для браузера могут свести до нуля преимущества дальнейших быстрых переходов. Дело в том, что нет популярной и простой реализации, в которой не было бы сопутствующих расходов.

Простая html-страница всегда загрузится быстрей SPA-приложения. Другое дело, последующая навигация. Внутренние переходы у SPA-сайта, всегда будут и удобней, и быстрей.

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

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

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

😀
Подождите, нам надо время, чтобы загрузить наше быстрое приложение.

Помимо необходимости загружать и выполнять дополнительные скрипты, появляется дополнительная нагрузка из-за серверного рендернига. Сайт, который собирается в браузере CSR (Client Side Rendering), не будет проиндексирован поисковыми системами. Сервер возвращает только код для сборки. Содержание и html, которые нужны поисковым системам, загружаются отдельными запросами в фоне браузера в процессе сборки. Поисковые боты такие фоновые запросы не выполняют. Для индексации поисковыми система требуется серверный рендеринг — сборка сайта на сервере SSR (Server Side Rendering).

🔗
Подробнее об SSR в статье Rendering on the Web. https://web.dev/rendering-on-the-web/

Сборка html сайта на сервере с использованием современных фреймворков, таких как Angular, Vue.js, React, Svelte, требует выполнение дублирующей полной или частичной сборки html в браузере. На сервере формируется html без обработки действий пользователя. Чтобы добавить обработку, нужно пересобрать исходники компонентов в браузере, потому что обработка действий связана со сборкой html и активироваться может только в среде браузера (CSR), но не в среде сервера (SSR).

Код для обработки действий пользователя необходим для графиков, анимации, таймеров, форм, галерей, всплывающих окон, выпадающих меню и т.п.

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

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

Сопутствующие расходы, для SPA:

  1. Требуется код для реализации переходов.
  2. Требуется код для сборки сайта в браузере.
  3. Требуется сборка сайта на сервере.
  4. Требуется сборка сайта в браузере.
Для традиционного сайта требуется только сборка сайта на сервере. Сервер передаёт содержание браузеру вместе с интегрированным в содержание кодом для обработки действий пользователя.

Медленная работа сайта, при первом посещении, очевидно, не улучшает первое впечатление пользователя. Дальнейшие преимущества по скорости, снижению нагрузки на сеть, плавные переходы могут быть бессмысленными, если пользователь просто не дождётся их и закроет сайт.

Сайт который загружается за 1 секунду имеет конверсию в 3 раза выше, чем сайт, который загружается за 5 секунд.

🔗
A site that loads in 1 second has a conversion rate 3x higher than a site that loads in 5 seconds. https://www.portent.com/blog/analytics/research-site-speed-hurting-everyones-revenue.htm

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

Angular

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

🔗
In practice, you'll serve a static version of the landing page to hold the user's attention. At the same time, you'll load the full Angular application behind it. This means that the application generally renders more quickly, giving users a chance to view the application layout before it becomes fully interactive. https://angular.io/guide/universal

Vue.js

Чтобы приложение полность заработало после сборки на сервере, необходимо в браузере выполнить процедуру “гидратации”, после которой приложение будет полностью функционально.

🔗
Vue.js is a framework for building client-side applications. By default, Vue components produce and manipulate DOM in the browser as output. However, it is also possible to render the same components into HTML strings on the server, send them directly to the browser, and finally "hydrate" the static markup into a fully interactive app on the client. https://vuejs.org/guide/scaling-up/ssr.html

React

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

🔗
React will attempt to attach event listeners to the existing markup. https://ru.reactjs.org/docs/react-dom-client.html#hydrateroot

Сборка сайта поисковыми системами

Google и Яндекс работают над возможностью индексации SPA сайтов и у них есть, решения для выполнения браузерного кода. Но, надо понимать, что для поисковых систем выполнять код миллионов сайтов, весьма, затратное занятие. Такой сайт, если он не Википедия, у которой конечно есть SSR, не может рассчитывать на приоритетное индексирование по сравнению с обычными сайтами. Отсутствие у сайта SSR, значительно усложняет жизнь поисковым система. Нет точных данных — как отсутствие SSR у SPA-сайта влияет на позиции в поиске и как быстро, и как успешно сайт будет добавлен в индекс. Также, у SPA-сайтов, в принципе, бывают проблемы с кроссбраузерностью из-за использования современных технологий. Не все браузеры могут правильно собирать сайт без дополнительных прибамбасов — полифилов, компиляторов, сборщиков. Теперь ещё нужно гарантировать, что сайт будет работать в невидимой среде поискового бота. Работу в браузере можно увидеть, а работу сайта для поискового бота можно оценить только по итоговому наличию сайта в поисковой выдаче.

🔗
На индексацию, обычного или SPA-сайта с поддержкой SSR, поисковым системам требуется около недели. Сайт без SSR скорей всего проиндексирован не будет. Робот Яндекса может проиндексировать AJAX-сайт (SPA), если у каждой страницы сайта есть HTML-версия (SSR). https://yandex.ru/support/webmaster/robot-workings/ajax-indexing.html

И хотя, как сказано выше, у поисковых систем есть решения, но полагаться на них не принято. Если для сайта критично присутствие в поисковой выдаче, должна присутствовать сборка html сайта на сервере.

Что в итоге?

Получается так. Мы открываем сайт, который собирается на сервере. Потом этот сайт вместе с кодом сборки и кодом переходов передаётся в браузер, где сайт снова, второй раз, собирается. А потом мы получаем преимущество быстрых и плавных переходов.

Из-за этих сложностей технология не получает широкого распространения среди небольших маркетинговых проектов, когда важно первое впечатление, и наоборот, является промышленным стандартом в банковских приложениях и разных сложных сервисах, где:

  • важно удобство при продолжительной работе
  • индексация поисковыми системами не требуется.
  • долгую первую загрузку можно скрасить картинкой “С добрым утром — сейчас всё будет”.

Так есть ли решение для маркетинговых проектов?

Да, можно получить скорость и удобство SPA-сайта без нагрузки на точку входа.

С каждым годом появляются новые технологии, и в браузерах, и на сервере, которые упрощают реализацию и уменьшают “стоимость” сопутствующих расходов, на столько, что выигрыш становится всё более значимым, а сопутствующие расходы уже можно свести к нулю.

Устраняем сопутствующие расходы

1. Требуется код для реализации переходов

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

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

  • Modules
  • Fetch
  • Promises
  • Service Worker API
  • back/forward cache
  • Template literals (Template strings)

Более того, даже эти 20 строчек можно подключить, когда произойдёт клик, то есть, значительно позже первого впечатления. Точка входа загружается без SPA-кода. Потом, при первом внутреннем переходе, потратится время на подключение нужного кода, но этот переход всё равно будет быстрей, чем такой же переход с полной перезагрузкой. Такой подход позволяет гарантировать, что SPA-приложение не добавляет никакой дополнительной нагрузки при первой загрузке и работает быстрей при последующих переходах.

При реализации SPA переходов по сайту нужно обработать якоря в ссылках с прокруткой до нужного блока — по умолчанию браузер прокручивает сразу, без ожидания нового содержания. Отладить кнопки вперёд назад, которые должны запоминать прокрутку и восстанавливать нужное состояние. Скрипты в загруженном блоке надо выполнить. При смене состояния должны поменяться meta-теги в head — title страницы, картинка превью и т.п.

2. Требуется код для сборки сайта в браузере

Появились ключевые технологии, которые позволяют отказаться от громоздких решений, в частности, отказаться от нестандартных шаблонизаторов. Плюс правильная архитектура всего приложения, когда всё модульно, слабосвязано, с минимальной сложностью кода. И главное, код сборки html сайта отделён от кода обработки действий пользователя. Другими словами, код для обработки действий в браузере не имеет связи с фреймворком — это позволяет выполниться этому коду без загрузки фреймворка.

При первом посещении, код для обработки действий находится внутри html, точно также, как на традиционных сайтах. Тем самым, пропадает необходимость повторной сборки сайта в браузере если сайт собран на сервере.

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

🛠
Маленькая хитрость. Как подменить клик по всем ссылкам, не дожидаясь загрузки и появления всех ссылок? Любой клик в браузере доходит до объекта окна window и даже тогда, стандартный переход можно всё ещё отменить. Таким образом, достаточно ждать действия пользователя на верхнем уровне, а далее уточнить на каком непосредственно элементе произошёл клик и если это ссылка, то запустить переход в новое состояние без перезагрузки страницы. Такое решение позволяет не добавлять на каждую ссылку персональный обработчик и всё становится чуть-чуть проще. На каждую сложность, со временем, можно найти какое-то простое решение.

3. Требуется сборка сайта в браузере

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

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

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

4. Требуется сборка сайта на сервере

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

Общие проблемы

Надо отметить, что сопутствующие SPA-сайтам уникальные расходы не являются самыми большими и критическими для сайта. Просто это статья про SPA и этим расходам уделено всё внимание.

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

Влияние затраты на SPA при первом визите можно оценить от 0 до 500 мс в сети G3. Против затрат от 100 до 5000 мс при проблемах на backend’е.

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

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