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

В сегодняшней статье мы бы хотели поделиться опытом успешной модернизации с помощью Аdobe Experience Manager и рассказать, как применить данное решение для мультиканального сайта.


Читать далее

Лирическое отступление об Аdobe Experience Manager: что это такое и зачем нужно
Adobe Experience Manager, ранее скрывавшаяся под названиями CQ5, Day CQ5 и Adobe CQ5, — это система управления веб-контентом, предназначенная для создания, редактирования, управления и оптимизации веб-сайтов по различным цифровым каналам. AEM не зависит от платформы и функционирует на Java-сервере. Позволяет создавать любое количество веб-страниц/сайтов благодаря использованию реюзабельных компонент и шаблонов.


Модернизация не самого современного, но довольно простого сайта — задача интересная, но, как говорится, без «изюминки». Другое дело, когда сайт заказчика представляет собой более пятидесяти различных бизнесов, для каждого из которых используется свой набор технологий (hybris, .NET, Java и т.д). Объединить все вышеперечисленное в одну идеально работающую систему и качественно обновить каждый канал сайта — это своего рода challenge, но не бывает ничего невозможного.

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

Почему Adobe Experience Manager?


Данное решение обладает теми возможностями, которые идеально подходят для оптимизации мультиканального сайта. Прежде всего, это высокий уровень многократного использования базовых компонент и секций (как back-end, так и front-end), что в нашем случае крайне важно, так как их можно оптимизировать под новые каналы, доработав недостающую функциональность, и тем самым сократить время и усилия. Второй момент — поддержка интернационализации и локализации из коробки, что значительно упрощает разработку, поскольку у заказчиков есть планы по расширению бизнеса на другие страны. AEM — это также content management и experience management система, которая обладает большой гибкостью в управлением тем, что мы видим на сайте. Среди прочего, это редактирование контента: возможность разбиения функциональности на модули и управления ими без привлечения программистов и написания кода, создание back-end логики благодаря технологии OSGi, масштабирование и персонализация контента.

Модернизация: что использовали, что сделали и почему


Как уже понятно из текста выше, за основу мы взяли технологию Adobe Experience Manager благодаря ее возможностям и удобству для администраторов. Разумеется, использования одной этой технологии было недостаточно. На основе Bootstrap мы переработали статический шаблон сайта, добавив back-end часть и бизнес-логику (появилась адаптивная верстка, в том числе для мобильных устройств, использовался HTML 5, в общем, добавили все плюшки, свойственные современным сайтам). Также мы доработали функциональность и оптимизировали производительность под разные виды устройств, добавили дополнительные архитектурные решения по масштабируемости приложения через добавление облачных сервисов.

Поскольку многие направления бизнеса заказчика сходны между собой, было принято решение создать компоненты для многократного использования. Зачем каждый раз разрабатывать новую компоненту для другого канала, если по сути она одна и та же, просто иначе сконфигурирована (разный текст или способ отправки данных на сервис)? Для различных бизнес-кейсов мы настроили базовые и специфичные опции для компонент, что упростило их использование в сходных случаях. Благодаря подобному решению добавление новой функциональности и интеграция сервиса стали гораздо прозрачнее. Конечно, небольшие обновления на back-end необходимы, чтобы научить сервис понимать новое поле, но сам front-end стал намного проще. Теперь, чтобы добавить новую функциональность, необходимо зайти через редактор, совершить необходимые манипуляции по конфигурации компоненты в зависимости от ее назначения и результатов smoke-тестирования, и опубликовать страницу.

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

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

Как мы это сделали? Для реализации подобной функциональности, взаимодействия между компонентами и сохранения и отправки на сервис, мы интегрировали возможности Adobe Experience Manager и Angular.js. Например, для управления логикой отображения у каждой компоненты, используещейся в АЕМ, есть поле в конфигурации, которое называется visibility. Это поле определяет, будет ли видна компонента пользователям или нет. Стоит признать, что поле не самое удобное в применении, но благодаря ему можно использовать не чистый JavaScript для написания каких-то функций, а интегрировать компоненту в эко-систему Angular. Примером здесь может послужить выражение user.answers.dateOfBirth > 01-01-1970, выполняющее валидацию по дате рождения, которое подставляется в ng-if директиву, оборачивающую заданный компонент. Благодаря наличию two-way binding в Angular внесение изменений в какое-либо поле не остается незамеченным, так как все они объединены в единое целое. После внесения изменений происходит пересчет, должны ли мы теперь показывать данное поле или нет.

Что ещё интересного использовалось?


Ещё одно любопытное решение, которое мы применили, — это отделение схемы хранения данных на front-end от схемы отправки на back-end. Поскольку сайт заказчика во многом состоит из форм для заполнения, мы сделали так, что ответы пользователя сохраняются в local storage (функциональность HTML5) в формате JSON. Далее происходит разделение данных, предназначенных для front-end и back-end, и отправка последних на АЕМ для последующей трансформации. Преобразование входящих данных в схему сервиса происходит на уровне интеграции front-end части с REST-сервисами, которые и занимаются поиском подходящих услуг для пользователей сайта. Таким же образом мы совершаем преобразование данных и в обратную сторону: если пользователь залогинен и хочет выбрать что-то из уже заполненных данных, то опять происходит трансформация данных, которые предоставляет REST-сервис, в формат данных, используемых на front-end. Чтобы этого добиться, мы каждую интеграцию с сервисом (например, отправку данных на сервис, занимающийся поиском наиболее подходящих продуктов в базе ), описали в соответствующем формате и сохранили в АЕМ-репозитории в виде структурных нод.

Описание трансформации в виде нод в репозитории
Мы берем выходной JSON, который будет использоваться для отправки на сервис, и описываем его в том же формате, в котором должен быть исходящий JSON, т.е. структура нод в репозитории повторяет структуру JSON-документа. Каждая нода может быть просто использованием одного из значений из входящего JSON. В случае какой-то более сложной логики, мы можем использовать server-side JS для трансформации входного JSON в выходной. К примеру, мы знаем, что в JS-файле, который находится под нодой, есть функция transform, которая должна вернуть выходящие данные. Если требуемое поле не пусто и определено, то мы его возвращаем. Если же оно пусто, то мы возвращаем заранее заданное значение — единицу. Это пример несложного преобразования данных из одного формата в другой с использованием JavaScript. Исполнение скриптов, лежащих в репозитории и описывающих трансформацию входных данных в выходные, выполняется JS-движком Rhino, полностью написанным на Java.


Возможности по персонализации


АЕМ хорош тем, что предоставляет отличные возможности для персонализации контента. В нашем случае, мы воспользовались модулем, который поставляется из коробки вместе с фреймворком, оптимизировали его под себя, создав дополнительные сегменты пользователей к уже существующим. Что получилось в итоге? Главная страница канала стала персонализированной, имеет приветствие и отображает историю запросов пользователя. В случае, если пользователь выйдет из аккаунта, страница все ещё будет помнить имя пользователя, но уже предложит залогиниться. Если же пользователь будет настаивать, что система ошибается, и это совсем не он/она, то им будет предложено использовать сайт в качестве анонимного пользователя, и в данном случае будет показываться совершенно другой контент. В принципе, на все типы пользователей можно настроить различный контент, вплоть до удаления приветствия и замены его на какую-то другую компоненту. Для этого нужно создать новый компонент, а администраторам сайта сконфигурировать его, то есть выбрать правила из заранее доступного набора, в каком случае этот компонент должен показываться.

Однако не все так просто, как выглядит…


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

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

Сама архитектура сайта представляет собой пассивный кластеринг, и в данный момент у нас три сервера приложений, которые служат для обработки запросов пользователей. Однако все построено таким образом, что в случае каких-либо проблем с производительностью, мы можем довольного легко и быстро начать горизонтальное масштабирование системы. С помощью скриптов развертывания, через Vagrant/Docker и Amazon Cloud мы можем поднять виртуальную машину, установить АЕМ и развернуть на ней последние исходники нашего сайта, добавив ее во всю эко-систему приложения.

Что касается производительности, в особенности на мобильных устройствах, то поскольку мы использовали Angular, легко было уйти в непроизводительное приложение с большим потреблением процессора на клиенте. В данном случае нам помогла оптимизация структуры HTML, использование one-way binding для уменьшения количества watcher-функций на Angular и переписка некоторых Angular-директив.

Для оптимизации производительности самого сайта применяется высокий уровень кэширования данных. Большая часть контента, которую видят пользователи, является статической информацией, которую выдает веб-сервер — мы значительно снизили количество обращений к серверу приложения. Это обуславливается best practices работы с АЕМ, так как в большинстве проектов есть диспатчер, который служит для кэширования статической информации. В идеале, запрос на сервер приложения должен доходить только в случае, если поменялись данные на самом сервере или сайте либо туда выкатился новый код.

Также очень много улучшений мы сделали, чтобы добиться высокой Google page score статистики. Чтобы по максимуму использовать кэш браузера, мы оптимизировали количество запросов на сайт через конкатенацию JS, CSS и т.д., объединение картинок в спрайты, SVG-подходы, fingerprinting-функциональность. Это, конечно, не что-то сверхестественное, но забывать об этом тоже не стоит.

Заказчикам в любом случае нужна ваша помощь


Не смотря на все плюсы AEM, заказчикам в любом случае нужна ваша помощь в разработке компонент, необходимых специально для какого-то конкретного направления, либо описание каких-то экзотических сценариев вроде добавления нового сегмента пользователей и т.д.
Разумеется, технически здесь есть ещё поле для развития: можно бесконечно упрощать JavaScript, создавать новые high-level функции, которые заказчики смогут использовать в дальнейшем, и многое другое.

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

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