Полностью обновили код и разработали дизайн сайта alta-profil.ru. Сделали его удобнее, быстрее и информативнее для пользователей.

«Альта Профиль» — производитель отделочных материалов из полимеров, с которым мы работаем уже много лет по разным направлениям. 

В этом кейсе рассказали об обновлении сайта: с какими проблемами столкнулись и как их решали.

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

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

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

Рефакторинг не является процессом создания нового функционала или исправления ошибок на сайте, это улучшение уже существующего кода

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

В техническом плане перед нами стояли 3 задачи:

  • Переход на реактивный фреймворк, в нашем случае Vue.js 

  • Серверный рендеринг, чтобы не потерять позиции в SEO при переходе на Vue.js

  • Корректная маршрутизация 

Теперь подробнее о решении каждой из них.

Переход на реактивный фреймворк: почему Vue.js 

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

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

 На рынке сейчас два основных фреймворка:

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

React —  реактивный фреймворк от компании Meta* (запрещенной на территории РФ), основанный на управлении компонентами.  Компонентный подход — ключевая особенность React, которая позволяет создавать переиспользуемые компоненты для отображения интерфейса.

Для решения нашей задачи мы предпочли Vue.js, так как фреймворк:

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

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

Серверный рендеринг: как не потерять позиции при переходе на Vue.js

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

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

Для решения этой задачи мы использовали Nuxt.js — фреймворк на основе Vue.js, который обеспечивает серверный рендеринг

 Расширение закрыло все наши задачи в рамках разработки, о которых мы говорили выше:

Серверный рендеринг

Расширение запускается, как серверная часть, генерирует HTML-код и отправляет его браузеру. Если запрос приходит от поискового робота, то он отправляет полную версию страницы, при запросе от пользователя он передает «незаполненную верстку», а остальные динамичные данные рендерятся уже на стороне самого пользователя.

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

Роутинг

Маршрутизация внутри проекта — все, что связано с движением пользователя по сайту.

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

Nuxt.js предоставляет роутинг «из коробки» — его не нужно настраивать отдельно. В расширении используется файловая система для автоматического генерирования роутов на основе структуры файлов и каталогов, которая выглядит примерно так:

pages/
--| index.vue
--| about.vue
--| contact/
-----| index.vue
-----| email.vue

Как видно из приведенного выше примера, файлы Vue-component располагаются в директории pages. Каждый файл — маршрут, соответствующий URL-адресу. Таким образом, index.vue соответствует корневому маршруту (`/`), `about.vue` – маршруту `/about`, а `contact/index.vue` – маршруту `/contact/`.

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

Работа с метатегами

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

Глобальный <head>. Nuxt.js предоставляет <head> объект в файле `nuxt.config.js`, который используется для установки глобальных метатегов для всего сайта:

// nuxt.config.js
export default {
  head: {
    title: 'My Website',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' }

Помимо дефолтных метатегов, кодировки и отображения видимой области в данном блоке настроек можно, например, внедрить различные сторонние скрипты: GTM, метрики, live-чаты и т. д.

Локальный <head>. Локальные метатеги для каждой страницы через компонент Vue.js.  Устанавливаются метатеги для любой страницы при добавлении объекта <head> в компонент:

<script>
export default {
  data() {
    return {
      title: 'My Page',
      description: 'This is my page description'
    }
  },
  head() {
    return {
      title: this.title,
      meta: [
        { hid: 'description', name: 'description', content: this.description },
      ]
    }
  }
}
</script>

В этом примере мы устанавливаем title и description метатеги для локальной страницы. Значение `hid` используется для предотвращения дублирования тега на странице.

Чтобы определить общие метатеги для всех страниц сайта, можно создать `layout` компонент и определить глобальные метатеги в нем.

Динамические метатеги. Основанные на динамических маршрутах. Для этого обычно используется  asyncData  для получения дополнительных данных, таких как title и description. В нашем случае, мы использовали fetch – более современное решение асинхронного получения данных, которое не ограничено компонентами страниц. При этом метод fetch расширяется свойством fetchOnServer,  указывающим  необходим ли вызов fetch при рендеринге на сервере. Тут происходит магия — для поисковых роботов fetchOnServer всегда возвращает true, а для пользователей —  значение зависит от значимости контента и требований к его показу.

Вот пример использования `fetchOnServer` в Nuxt.js:

<template>
  <div>
    <h2>{{ post.title }}</h2>
    <p>{{ post.body }}</p>
  </div>
</template>

<script>
export default {
  head () {
    return this.post
  },
  fetchOnServer () {
    return this.isSearchBot()
  },
  async fetch () {
    // Выполнение запроса и предварительное заполнение vuex store
    const post = await this.$axios.$get(`https://jsonplaceholder.typicode.com/posts/${this.$route.params.postId}`)
    this.$store.commit('setPost', post)
  },
  computed: {
    post() {
      return this.$store.state.post
    }
  }
}
</script>

В этом примере мы определяем метод fetch, выполняется на сервере, до того, как компонент будет отрендерен, или на клиенте — в зависимости от состояния возвращаемого fetchOnServer, результат которого зависит от того, кто открывает страницу: поисковый робот или пользователь. Внутри метода мы используем `$axios` для выполнения запроса к API "jsonplaceholder". Полученные данные сохраняются в Vuex Store с помощью `store.commit`. 

Получив данные, мы можем использовать их для отображения в шаблоне Vue.js внутри метода `computed`.

Мы рефакторили сайт на Bitrix, где уже были настроены все метаданные. Чтобы их не потерять, мы написали отдельный API — метод, который по роуту генерирует и возвращает ранее сформированные шаблоны метатегов. Так мы перенесли все старые метатеги на новый сайт

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

Комментарии (13)


  1. diakin
    00.00.0000 00:00

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

    Ну да, быстренько получается. Хотя скриптов и css на 11 метров.


    1. completoru Автор
      00.00.0000 00:00

      Спасибо за комментарий
      Не совсем 11: 5мб, сжатое 1.34  http://joxi.ru/82QXkB1U3ZQ3Vm.

      Самые тяжеловесные скрипты https://share.cleanshot.com/wWk4wvw5 грузятся асинхронно, если их вычесть, то на сайт для рендеринга остается не так много и поэтому скорость ок.

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


      1. asked2return
        00.00.0000 00:00

        может он про ram


  1. metter
    00.00.0000 00:00

    Заметили какие-то изменения по позициям сайта в поисковых системах?


    1. completoru Автор
      00.00.0000 00:00
      +1

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


  1. Starina_js
    00.00.0000 00:00

    На беке битрикс с админкой оставили? Или новое написали?


    1. completoru Автор
      00.00.0000 00:00

      Оставили «Битрикс» для управления контентом 


  1. PaulZi
    00.00.0000 00:00

    Рендеринг на клиенте не быстрее чем рендеринг на сервере, т. к. вместо того, чтобы вашему браузеру сразу отобразить готовый html, ему приходится его собирать из данных и скриптов. Другое дело если у вас бэкенд (Битрикс) тормознуто его собирал, но это уже другая проблема.


  1. Farmatique
    00.00.0000 00:00
    +1

    Следующим шагом может быть, вероятно, генерация статических страниц на сервере вместо SSR. Причем nuxt это уже из коробки умеет


  1. ScorpAL
    00.00.0000 00:00

    Ну и нагородили!

    А на мобилке многие элементы по три раза тыркать приходится что бы попасть в них.


  1. dagot32167
    00.00.0000 00:00
    +2

    После прочтения статьи я так и не понял, как вы ускорили сайт в 10 раз, зачем вы переходили на Nuxt, что в итоге изменилось?
    поясню
    Не хватает контекста, что именно пытались исправить. Если вы ускорили сайт:
    - Или улучшили перформанс лайтхауса в 10 раз, то он раньше был 4? https://pagespeed.web.dev/analysis/https-www-alta-profil-ru/726ug8gc7y?form_factor=mobile - тут ща на мобилке (десктоп не смотрим, он ни на что не влияет) 43 балла.
    - Или вы изменили метрики Web Vitals? но тогда какие они раньше были?
    - Или метрики из RUM и ваш конечный пользователь смог быстрее навигироваться.
    - Или какой нить пресловутый 95 перцентиль на GET запрос за HTML или данными из бековых систем.
    Ради чего переход на Nuxt и с какой именно технологии? Почему именно Vue? ИМХО, личный опыт показывает, что на РУ рынке проще найти квалифицированного (мидла или сеньора) react разработчика, а вот vue сложнее.
    Зачем было переходить на Vue и оставлять подключенный jquery?
    Как изменился time-to-market при смене технологического стека, ведь по сути ради этого вообще весь "рефакторинг".
    Сколько времени занял перевод со старого стека на новый, силами скольких разрабов? Сколько было изменено сопутствующих систем, пайпланов и тестов (я вижу на сайте товары с ценой в ноль рублей, могу их положить в корзину и даже оформить заказ. Проверь заказ №С-201687. вы конечно написали, что все что на сайте не публичная оферта, но такое)?
    Как переход на новый стек изменил объем органического трафика и уникальных пользователей, конверсии в корзину?
    Статья больше про куски Nuxt, но не про ускорение.


  1. ZolotoArtem
    00.00.0000 00:00
    +1

    "Мы предложили провести рефакторинг с переходом на реактивный фреймворк, когда верстка и дизайн сайта рендерятся на стороне пользователя.  За счет этого загрузка происходит практически мгновенно"

    "В техническом плане перед нами стояли 3 задачи:
    Серверный рендеринг, чтобы не потерять позиции в SEO при переходе на Vue.js"

    Так много вопросов и так мало ответов.

    Реактивный фреймворк - это не про рендер на стороне пользователя и мгновенную загрузку. JS и jquery тоже могут рендерить на стороне пользователя. А мгновенной загрузки добиваются абсолютно другими методами. Вам просто нужно было продать vue и вы немного навешали лапши. При этом нет у вас никакого клиентского рендеринга, потому что вы сами сказали, что он серверный. Получается и тут обманули


  1. AndreyVSmirnov
    00.00.0000 00:00
    +1

    Хотел написать о нескольких найденных минусах. О плюсах написано в статье.
    Для главной страницы Google PageSpeed Insights GPSI) говорит, что всё ОК. Но если запустить его для /catalog/, то результат будет заметно хуже. А для фотогалереи лучше и вовсе не запускать GPSI.
    Видно, что в самом Битрикс познания не глубокие, т.к. в фильтре каталога допустимо выбрать цвет "Красный" и материал "Крашеный", а в результате получить "Ничего не найдено". Такой результат ещё допустим при использовании ползунка цены, но при выборе значений из списков... Т.н. "Умный фильтр" решает эту проблему.
    Формы валидируются только на фронте.
    Фотографии в разделе "Фотогалерея" не оптимизированы.
    В отзывах фейковая пагинация. На страницу загружаются сразу все отзывы. В новостях, сертификатах аналогично. А если отзывов будет 10 000? Правда сами отзывы тоже фейковые. Так что можно сильно не беспокоиться, что их будет много, ОК.
    На странице /catalog/promo/spc-napolnoe-pokrytie/ куда-то улетел футер. Если в последнем блоке сменить коллекцию, то вообще не понятно что происходит.
    И т.д. На многих страницах можно найти довольно спорные решения.
    Такой рефакторинг нужно будет снова рефакторить.