В Pipedrive мы использовали Craft CMS, систему с открытым исходным кодом, для создания нашего общедоступного сайта Pipedrive. У нас был ряд надежных компонентов, таких как Основной блок, Отзыв, Расширенный текст, Блок призыва к действию, и Блок цен, и это лишь некоторые из них. С помощью Craft CMS контент-менеджеры могут легко складывать эти фиксированные компоненты для быстрого создания страницы. Например, с блоком героев они могли просто выбрать изображение, добавить текст — и вуаля, все готово! Эта установка работала хорошо, но вскоре мы обнаружили, что назревают проблемы.

Проблема

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

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

У нас были четкие требования к нашей установке:

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

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

Мы потратили много времени на изучение различных популярных CMS. Все они были потрясающими и решили множество проблем, но им все еще нужно было проверить все наши флажки в отношении гибкости, настройки, простоты использования и бесшовной интеграции между нашими системами. Гибкость, которую обеспечивала Craft CMS, была непревзойденной. Еще одним важным фактором, повлиявшим на наше решение, было наше знакомство с Craft CMS. Итак, мы вернулись к нашей существующей неэффективной настройке и спросили себя: правильно ли мы настроили нашу текущую систему? Ответ смотрел прямо на нас в течение последних нескольких лет: нет. По счастливому стечению обстоятельств, это произошло примерно в то же время, когда Craft CMS выпустила версию 3.5 RC, значительно переработанную. Среди других интересных изменений наше внимание привлек новый конструктор макетов полей.

Имея под рукой эту новую версию, мы решили глубже погрузиться в Craft CMS, позволяя контент-менеджерам легко создавать и изменять веб-страницы, не создавая непонятного лабиринта полей. Хотя Craft CMS предлагала надежные типы полей, нам нужно было что-то большее. Именно тогда мы обнаружили плагин craft-neo. Это было похоже на появление супергероя, чтобы спасти положение и открыть целый новый мир возможностей. На тот момент мы были уверены, что перестроим общедоступную веб-архитектуру, отвечающую всем нашим требованиям, а также простую в использовании.

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

План

Для работы системы нам понадобилось несколько частей:

  1. Библиотека дизайна;
  2. Настройка CMS;
  3. Постпроцессор: здесь выполняются переводы и другие улучшения ввода; и
  4. Рендерер.

Библиотека дизайна

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

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

После обширных исследований и планирования мы разделили наши проекты на более мелкие части. Как только у нас появился четкий план, мы, засучив рукава, построили эти компоненты. Мы решили создать его с помощью React.js по нескольким причинам. Во-первых, React широко использовался и рекомендовался в Pipedrive. Кроме того, выбранная нами оболочка интерфейса, Next.js, построена на основе React, что делает ее естественной для нашего проекта.

Мы разделили части библиотеки на пять основных частей:

  1. Ядро. Основа всего, что встроено в нашу общедоступную сеть. Это необходимо для сборки других компонентов;
  2. Элементы. простые строительные блоки для Интернета. Они являются либо реализацией ядра, либо комбинацией других элементов;
  3. Компоненты:строительные блоки, которые нуждаются в оболочке и имеют смысл. Они могут состоять из ядра, элементов и других компонентов; и
  4. Шаблоны. Большие строительные блоки, расположенные или соединенные определенным образом.

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

Настройка CMS: создаем!

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

Целевые страницы требовали большей части наших усилий, так как они не могут содержаться в единственном макете. Для этого мы создали Раздел под названием Лендинг, а структура поля выглядела так:

  1. Мета: информативная, высокоуровневая, описывает саму страницу;
  2. Контент: все самое интересное! Здесь создаются компоненты; и
  3. SEO: переопределение настроек SEO по умолчанию и добавление дополнительной связанной информации.

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

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

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

Мы столкнулись с проблемой при отображении сетки между разными экранами. Мы решили эту проблему, разделив область просмотра на максимальное количество столбцов для каждого типа: настольный компьютер, планшет и мобильный. Максимальное количество столбцов — 12, 6 и 3.

Свойство Size определяет ширину (столбцов) столбца относительно экрана. Выбор максимального числа означает, что он всегда занимает всю ширину области просмотра.

К каждому компоненту в CMS прикреплены как минимум три элемента данных: Имя, Свойства и Дочерние элементы. Значения Properties передаются его аналогу компонента пользовательского интерфейса, а Children — это другие компоненты, которые он охватывает (помните модель композиции, о которой мы упоминали ранее?).

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

{
 "id": 123,
 "title": "Test entry title",
 "slug": "test-entry-title",
 "enabled": true,
 "structure": [{
  "name": "container",
  "properties": {
   "theme": "default"
  },
  "children": [{
   "name": "flexRow",
   "properties": {
    "horizontalAlign": {
     "xs": "center",
     "s": "center",
     "m": "center"
    },
    "column_verticalAlign": {
     "xs": "start",
     "s": "start",
     "m": "start"
    },
    "verticalGap": {
     "xs": "none",
     "s": "none",
     "m": "none"
    },
    "direction": "row"
   },
   "children": [{
     "name": "column",
     "properties": {
      "size": {
       "xs": "3/3",
       "s": "6/6",
       "m": "12/12"
      }
     },
     "children": [{
      "name": "button",
      "properties": {
       "type": "primary",
       "color": "default",
       "size": "m",
       "width": "auto"
      },
      "children": [
       "Try it free"
      ]
     }]
    },
    {
     "name": "column",
     "properties": {
      "size": {
       "xs": "3/3",
       "s": "6/6",
       "m": "12/12"
      }
     },
     "children": [{
      "name": "text",
      "properties": {
       "textAlignment": {
        "xs": "left",
        "s": "left",
        "m": "left"
       }
      },
      "children": [
       "<p>Create the stages of your sales funnel or use an existing template. Add your deals or import them automatically from a spreadsheet or CRM.</p>"
      ]
     }]
    }
   ]
  }]
 }]
}

Обратите внимание, что структура имеет список компонентов, и каждый компонент рекурсивно имеет имя, свойства и дочерние элементы (компоненты).

Процессор ввода переводит этот JSON, выполняет несколько шагов постобработки поверх него, а затем сохраняет его в базе данных. Далее последняя часть головоломки: рендерер.

Рендерер

Мы подошли к последнему кусочку головоломки, и наша задача — все соединить. Мы выбрали Next.js для работы. Готовые инструменты и функции Next.js действительно замечательны. Особого внимания заслуживает внимание с самого начала к производительности, и мы также оценили дополнительное удобство доступа к основным показателям веб-показателей в режиме реального времени через API.

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

Проблемы

  • Чем выше уровень настройки, тем сложнее его понять. Это требует более глубокого понимания системы и накладывает кривую обучения для новых контент-менеджеров. Поэтому крайне важно активно вовлекать команду по контенту в реализацию, собирать их отзывы, проводить демонстрации и повторять процесс.
    Чтобы упростить процесс, мы создали повторно используемые компоненты, контейнеры и блоки, которые можно создать один раз и использовать на нескольких страницах. Это устраняет разочарование от многократного создания одной и той же вещи.
  • Система быстро стала громоздкой и ресурсоемкой. Мы решили эту проблему путем вертикального масштабирования инфраструктуры системы, а также изучили вариант горизонтального масштабирования за счет использования централизованного кэша и механизма хранения сеансов, который поддерживает Craft.
  • Есть одна часть головоломки, которая ускользает от нас: многоразовый макет. Хотя Craft CMS обеспечивает большую гибкость, мы не смогли найти волшебный тип поля, который позволил бы нам создать макет один раз и повторно использовать его в нескольких записях, выбирая нужные компоненты.

Заключение

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