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

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

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

Как обычно, я выбрал свой любимый интерфейсный стек Nuxt / Apollo, который обеспечивает мощную систему кэширования, а также простую реализацию рендеринга на стороне сервера. Nuxt / Apollo также предлагает лучший уровень производительности, чем React / Next, но этот момент может быть предметом споров 😅.

Проведя быстрый тест между Contenful и Prismic для решения CMS, я выбрал Contenful, который обеспечивает более простую настройку API GraphQl и идеально сочетается с Apollo без добавления каких-либо дополнительных скриптов. Время отклика, API изображений и распространение тоже хороши.

Следующие принципы можно легко применить к приложению Svelte или React.

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

Ниже приведен пример запроса graphQl для страницы, а также наименования наших типов, соответствующих именам наших компонентов Vue:

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

Ниже представлен массив, возвращаемый из запроса страницы, видимый из инструмента разработки Apollo:

На этом этапе мы можем перебрать наш массив componentCollection и динамически загрузить соответствующие компоненты:

Динамический импорт компонентов - хорошая практика, если вы повторяете большое количество таких компонентов:

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

В этом примере:

  • переменная «ширина» - это (ширина экрана * плотность экрана) / (общее количество столбцов вашей сетки * количество столбцов, на которые распространяется изображение).
  • переменная «format» - это расширение запрошенного изображения, в моем случае «webp» с откатом на «png», если оно не поддерживается.
  • качество - по шкале от 0 до 100 - рассчитывается в соответствии со скоростью нисходящего канала и эффективным типом сети с возвратом к среднему значению качества для браузеров, не поддерживающих API сетевой информации.

Конечно, адаптивная логика может быть немного сложнее, поэтому вам может потребоваться дополнительная логика для переменной «width» в компоненте в соответствии с инструкциями CSS и шириной области просмотра.

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

Работа с асинхронными компонентами
Создание макета после получения ответа API сопряжено с определенными ограничениями, которые необходимо учитывать. Например, на уровне страницы подключенный хук не гарантирует, что разметка ваших дочерних компонентов доступна, они монтируются только после обновления данных Apollo. После этого вам может потребоваться использовать функцию $ nextThick, которая обеспечивает обратный вызов, когда Vue завершает распространение ваших изменений в DOM, что означает, что макет смонтирован и доступен для дальнейших манипуляций только в это время.
На стороне сервера. режим генерации, это не нужно учитывать, и это де-факто режим, который я бы рекомендовал, если ваши страницы не содержат слишком много логики.

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

Я нашел следующее решение: при создании нашего экземпляра ApolloClient в конфигурации кеша я использую плагин сопоставления фрагментов, который генерирует файл интроспекции на основе вашей схемы GraphQL. Затем я настраиваю пустой массив типов для каждого набора результатов запроса.

Заключение
В итоге были достигнуты следующие цели:

  • Полная свобода в плане компоновки.
  • Беспрецедентная производительность, я получил среднее время загрузки страницы 200 мс с отложенной загрузкой изображений и свойством CSS Content-visibility, установленным для компонентов - в режиме SSG.
  • Один запрос на страницу, независимо от разнообразия и сложности макетов.
  • Способ последовательной организации и поддержки вашей библиотеки компонентов с помощью элементарной логики дизайна / руководства по стилю.
  • Это также позволило мне легко добавить слой анимации на основе прокрутки в мои компоненты.
  • Масштабируемое и эффективное решение при начале работы с редакторами, копирайтерами, иконописцами и дизайнерами.

Спасибо за чтение,

Мне было бы любопытно услышать мнение разработчиков, которые также реализовали этот тип системы.