Множество команд сталкиваются с решением вопроса по управлению контентом на различных платформах — от веб-сайтов до мобильных приложений и интернет-магазинов. При этом, как правило, отсутствует единый инструмент, позволяющий эффективно создавать, изменять, хранить и передавать контент для отображения на всех платформах.
Кто-то приходит к самостоятельной разработке инструмента по управлению контентом с нуля. Другие смотрят в сторону готовых CMS решений (content management system/систем управления контентом), которые зачастую позволяют сэкономить время и затраты.
Меня зовут Лена. Мы в команде Enablement Platform провели пилот по сравнению нескольких популярных решений для CMS, накопленный материал показался интересным и полезным для веб-разработчиков, в результате появилась эта статья.
Поделюсь с какими проблемами мы столкнулись, какой подход выбрали для управления контентом и доставке данных до витрин. Если бы такой материал мы встретили раньше, он бы сэкономил нам много времени.
Оглавление
1. Вступление
2. Требования и критерии выбора
3. Классы CMS
4. Ситуация на рынке Headless CMS
5. Сравнение Headless CMS
6. UI систем и примеры моделирования
7. Заключение
1. Вступление
Решения класса CMS существенно различаются зрелостью и функциональностью. То, что отлично подходит для простого персонального блога или небольшого сайта, может не справиться с потребностями сложных корпоративных витрин. Для снятия этих ограничений возможностей конфигурирования недостаточно и может потребоваться существенная доработка CMS. Например, ограничения в моделировании данных, подходы к управлению и отображению различных типов контента, механизмы к ограничения доступности контента и т. д. Большинство CMS ориентированы на относительно простую модель данных с ограниченным типом связей между сущностями.
В МТС есть множество различных пользовательских витрин, которые позволяют клиентам узнать о продуктах компании:
- сайте;
- приложении;
- интернет-магазине;
- лендингах и т. п. (например, premium.mts.ru, kion.ru, music.mts.ru).
И на текущий момент в экосистеме МТС применяются различные инструменты для управления контентом. Возникла идея — проанализировать текущий рынок CMS и провести «пилотирование» выбранных инструментов. По результатам пилота оценить возможность оптимизации и унификации подходов к управлению контентом и передаче данных витринам.
Даже официальные обзоры на сайтах CMS, где решения сравнивают себя с конкурентами, содержат ошибки и неточности.
Поэтому сделать выбор только на основании описаний или обзоров, статей (в том числе на Хабре) и тематических рейтингов не удалось.
Задача вносила корректировку к требованиям. В первую очередь нам были интересны решения, которые позволяют работать не с простым контентом (как, например, статьи на сайте), а со сложной иерархичной структурой данных, связанными сущностями, вложенными компонентами и т. д.
2. Требования и критерии выбора
При выборе CMS учитывались общие требования к функциональности, возможности кастомизации и специфические потребности команды, обусловленные используемым ИТ-ландшафтом.
Основные критерии выбора:
- Open Source решение и лицензии без дополнительных ограничений, в том числе на использование в коммерческих целях — возможность кастомизации под потребности компании, использование в составе других продуктов;
- Headless CMS — ключевое внимание на управление данными, уровень представления реализуется внешними витринами и зависит от их специфики и потребностей;
- максимально близкое команде продукта по стеку — backend предпочтительно C#, СУБД MongoDB и PostgreSQL;
- поддержка GraphQL API — у нас активно внедряется данный подход межсистемного взаимодействия, поддержка GraphQL API упростит интеграцию решения в общий ИТ-ландшафт;
- возможность создавать свою модель данных — постоянно запускаются новые продукты, у каждой группы продуктов свои особенности и атрибутивный состав, поэтому важно иметь гибкие возможности по моделированию;
ПримечаниеПоддержка иерархичной модели данных, вложенных элементов, в одной родительской сущности можно создать несколько дочерних.
- поддержка SSO (Single sign-on) — данный механизм является стандартом в компании, позволяет пользователю не тратить время на авторизацию в каждой системе;
- работа с мультимедийным контентом: управление изображениями в различных разрешениях, видео контентом, бинарными документами и т. п.;
- наличие локализации — для перевода контента на различные языки;
- наличие версионирования контента — для отслеживания истории изменений и возможности отката к прошлым версиям;
- возможность управления workflow — управлением возможными статусами у сущностей, включая поддержку отложенной публикации контента;
- удобство использования;
- импорт контента из внешних источников — для упрощения процесса миграции на новую систему;
- производительность ~2000 RPS;
- информирование внешних систем об изменении данных;
- возможность генерации API по созданной модели — для сокращения трудозатрат на разработку;
- ролевая модель пользователей и API — для разграничения прав доступа к управлению контентом;
- мультитенантность — возможность управления контентом в одной CMS для нескольких команд, где у каждой из них свое пространство.
3. Классы CMS
Традиционные CMS
Позволяют как управлять данными, так и отвечают за их представление, поддерживают темы и т. д. На базе таких решений вы можете создать полностью готовый сайт с дизайном, фронтом и данными. Легко и просто наполнять его.
Типичные представители: WordPress, Joomla, Drupal.
Headless CMS
Предоставляет UI для управления моделью данных, UI для управлениям самими данными и основное — API реализующее набор CRUD операций на данными.
Именно через API происходит потребление этих данных внешними витринами и каналами.
Выделяют следующие типы решений:
- API Driven — используют СУБД для хранения данных (может использовать объектное хранилище для бинарных файлов);
- Git-based — используют Git репозиторий для хранения контента, как правило подходят для для простых задач, с небольшой частотой изменений.
Некоторые решения не предоставляет UI для управления моделями, модель описывается программным кодом.
4. Ситуация на рынке Headless CMS
Нас интересовали именно Headless-решения, потому что они позволяют моделировать контент с целью дальнейшего отображения на различных платформах. В нашем случае это вышеупомянутые витрины данных (сайт, мобильное приложение, интернет-магазин, лендинги и т.п.)
Бэкенд при данном подходе существует отдельно от фронта, что дает возможность использовать один бэкенд для хранения и передачи контента для отображения на всех вышеуказанных витринах данных. Это позволяет централизовать ведение данных по продуктам, а задачу их отображения и верстки оставить на стороне витрины. Потенциально мы даем необходимую гибкость продуктовым командам.
На рынке сейчас представлено большое количество Headless CMS. Когда мы делали выбор, какие из систем хотим «пощупать» (установить и попробовать смоделировать данные на примере нескольких продуктов), в первую очередь обращали внимание на популярность системы.
Поэтому первой начали рассматривать Strapi, которая является лидером на рынке и занимает первые места в многочисленных обзорах. В процессе столкнулись с серьезными багами и ограничениями, необходимостью глобальной доработки (включая бэкенд и модель СУБД). Несмотря на то, что в нашей команде есть JS-разработчики, трудно было переключить их от бизнес-задач к полноценной доработке бэка системы для продолжения пилота.
Мы решили посмотреть альтернативные Headless CMS на стеке .NET C#. При этом уже понимали, какие возможности нужны в первую очередь и на чем нужно сфокусироваться:
- поддержка использования компонент данных (набор элементов разных типов);
- массивы компонент;
- различные типы связи;
- набор UI контроллов для удобного наполнения данными.
Под наши запросы подошли Squidex и Orchard Core.
В процессе рассматривались и тестировались другие системы, но детально не анализировались, так как не удовлетворяли ключевым критериям. Как правило, были ограничения в моделировании данных.
Отпал ряд решений, которые не предоставляют UI для управления моделью, и модель задается прямо в коде.
В обзоре ниже представлены ключевые характеристики и особенности выбранных Headless CMS.
5. Сравнение Headless CMS
Squidex
| Сайт | squidex.io |
| Сообщество/поддержка | 2k stars Watchers 100 Forks 402 Contributors 60 Примечание
|
| Open source решение | Да. |
| Лицензия и ее классификация по SAM OSS лицензии | SAM 2.0 (mts.ru) | MIT license. |
| Версия на момент проведения анализа | 7.7.0 (01 Jul 2023) |
| Репозиторий | github.com/Squidex/squidex |
| Стек (frontend) | TypeScript / Angular / webpack / Node.js (development only — используется для сборки фронта)
Примечание
NodeJS нужна для разработки, если вы планируете дорабатывать UI админки на Angular. Все скрипты UI пакуются через webpack, а он использует NodeJS.
|
| Стек (backend) | C# / .NET 7 / ASP.NET Core |
| СУБД | MongoDB |
| Наличие GraphQL API | Есть, можно настроить скрытие определенных полей в API.
|
| Удобство создания и управления моделью данных, включая поддержку вложенности элементов | Можно несколько раз использовать 1 компонент.
|
| Поддержка SSO-авторизации | |
Особенности работы с мультимедийным контентом:
|
1. Изображение загружается с исходными параметрами, есть возможность тегировать изображения. В API есть возможность передать точные размеры и тип файла.
2. Да. |
| Наличие локализации | Да.
|
Поддержка версионирования. Рассматривали:
|
Сохраняется история изменений, можно сравнить с другими версиями и откатиться к нужной:
|
Возможность управления flow (статусы у сущностей).
|
Да, можно настраивать создавать новые статусы и условия перехода в них, а также определять последовательность шагов.
|
| Удобство использования | Самый удобный UI из трех, все интуитивно понятно.
|
| Особенности | В структуре JSON есть излишняя вложенность (с тем же столкнулись и в Orchard):
В GraphQL также:
Причина — реализация партиционирования (partitioning, используется для локализации). Примечание
The Content API usually returns one object per schema field where the keys are the languages (or iv for non-localized) fields and the values are the actual field value.
Key is iv, which stands for «invariant». docs.squidex.io/02-documentation/concepts/localization#how-to-use-the-api Для REST можно использовать заголовок X-Flatten Header, которые сделает плоскими данным с единственным значением. Для GraphQL можно использовать объект flatData:
|
| Импорт контента из внешних источников | При создании новой схемы в UI есть возможность импорта JSON-схемы,
пример
sq content export myschema —format=JSON sq content import myschema myschema_2020-05-20-09-14-34.json —format=JSON Импорт/экспорт данных с помощью CLI (подробнее тут: docs.squidex.io/02-documentation/developer-guides/automation-tools): |
| Хранение бинарных файлов (assets)/мультимедиа (S3 compatible) или интеграция с такой системой | AssetStore:
|
Нефункциональные требования.
|
Можно написать свой плагин для кэша.
Есть механизмы кэширования данных. |
Расширяемость (дорабатываемость) системы.
|
Предусмотрена расширяемость с помощью плагинов. |
| Публикация событий об изменении контента | Да. |
| Возможность генерации API по созданной модели | Генерация OpenAPI спецификации по модели и базовым методам.
Встроенный GraphQL браузер и документация по API. |
| Ролевая модель пользователей и API | Есть различные роли и можно добавлять свои: |
| Мультитенантность | Можно создавать пространства для различных команд: |
Strapi CMS
| Сайт | strapi.io |
| Сообщество/поддержка | 54.9k stars Watchers: 661 Forks: 6.7k Contributors 895 Примечание
Данные с github.com/strapi/strapi
|
| Open source решение | Да. |
| Лицензия и ее классификация по SAM OSS лицензии | SAM 2.0 (mts.ru) | MIT Expat для Публичной версии. |
| Версия на момент проведения анализа | 4.11.7 (19 Jul 2023) + плагины — установлена 21.07.2023 |
| Репозиторий | github.com/strapi/strapi |
| Стек (frontend) | JS/TypeScript
Angular |
| Стек (backend) | JS/TypeScript, Nodejs |
| СУБД | PostgreSQL MySQL/MariaDB SQLite |
| Наличие GraphQL API | Поддержка GraphQL с помощью плагина GraphQL | Strapi Market.
|
| Удобство создания и управления моделью данных, включая поддержку вложенности элементов | В рамках коллекции можно использовать несколько раз 1 компонент.
|
| Поддержка SSO-авторизации | Есть плагин. |
Особенности работы с мультимедийным контентом:
|
1. Изображения сохраняются сразу в трех размерах.
Примечание
Есть несколько плагинов, которые можно применить, если дефолтные настройки нас не устраивают:
2. Да. |
| Наличие локализации | Да. |
Поддержка версионирования. Рассматривали:
|
Нет.
Можно было бы создавать новые версии, используя функцию дублирования, но с учетом ее некорректной работы (не все поля дублировались, только простые, без компонентов) это проблематично. Для реализации версионирования нужны доработки. |
Возможность управления flow (статусы у сущностей).
|
Для ввода доп.статусов можно использовать плагин Review Workflows.
Также по ссылке есть пример, как использовать внешний автоматизатор n8n.
|
| Удобство использования | Не очень дружелюбный интерфейс бесплатной версии (не критично):
|
| Особенности | 1. Есть два режима запуска:
2. Слабая защита от «дурака» в UI можно изменить модель так, что система перестанет стартовать, и потребуется исправлять ошибки модели в исходных файлах проекта. Разработчикам (если они увидят нашу статью) было бы здорово обратить внимание на валидацию данных на UI (ограничение на количество символов в названиях объектов, запрет создания поля с именем «ID» и т. п.). |
| Импорт контента из внешних источников | Есть плагин. |
| Хранение бинарных файлов (assets)/мультимедиа (S3 compatible) или интеграция с такой системой | 1. В виде файлов в public/uploads на веб-сервере. 2. Коннекторы к объектным облачным хранилищам. |
Нефункциональные требования.
|
Есть плагин для кэширования данных. |
Расширяемость (дорабатываемость) системы.
|
Магазин плагинов.
Кастомные типы данных, для сложных случаев можно использовать объект с типом JSON (потребуется реализовать UI для управления данными). |
| Публикация событий об изменении контента | Да. |
| Возможность генерации API по созданной модели | GraphQL playground с документаций по API (после установки плагина). |
| Ролевая модель пользователей и API | Есть различные роли и можно добавлять свои:
|
| Мультитенантность | Через разработку, из коробки решения нет, но есть возможности настройки, которые не тестировались: Strapi-v4 | refine Есть плагин (также не тестировали): |
Orchard Core
| Сайт | orchardcore.net |
| Сообщество/поддержка | 6.7k stars Watchers 339 Forks 2.2k Contributors 242 This project is supported by the .NET Foundation. |
| Open source решение | Да. |
| Лицензия и ее классификация по SAM OSS лицензии | SAM 2.0 (mts.ru) | BSD-3-Clause license. |
| Версия на момент проведения анализа | 1.5.0 (04 Nov 2022) — была актуальна по состоянию на март 2023 |
| Репозиторий | github.com/OrchardCMS/OrchardCore |
| Стек (frontend) | JS/ASP.NET Core |
| Стек (backend) | ASP.NET Core |
| СУБД | SQL Server MySQL PostgreSQL SQLite using a document abstraction (YesSql) |
| Наличие GraphQL API | Есть.
|
| Удобство создания и управления моделью данных, включая поддержку вложенности элементов | Можно добавить Part в Content Type несколько раз (если выбрать настройку reusable).
|
| Поддержка SSO-авторизации | Есть плагин OpenId. |
Особенности работы с мультимедийным контентом:
|
1. Можно менять через appsettings.json.
2. Да. |
| Наличие локализации | Да. |
Поддержка версионирования. Рассматривали:
|
Судя по всему функция версионирования реализована через данный модуль Audit Trail module (Lombiq Technologies: OCORE-23) by domonkosgabor · Pull Request #6679 · OrchardCMS/OrchardCore · GitHub, но возможности не тестировались. |
Возможность управления flow (статусы у сущностей).
|
Возможность самостоятельно управлять статусами, а также событиями, по которой происходит их смена; допустима даже отложенная публикация/архивация через заранее заданное время Workflows — Orchard Documentation (orchardcore.net).
|
| Удобство использования | Можно настроить правила валидации для формы.
|
| Особенности | 1. Может работать в трех режимах, в том числе как Headless CMS:
2. Субъективно кажется, что структура в JSON усложняется неоправданно (добавляется формат поля), например:
|
| Импорт контента из внешних источников | Попробовали сделать импорт, структура по JSON не создается, импорт прошел успешно, но при этом результат никуда не сохранился.
Похоже, только импорт данных в уже созданную структуру. |
| Хранение бинарных файлов (assets)/мультимедиа (S3 compatible) или интеграция с такой системой |
|
Нефункциональные требования.
|
Можно написать свой плагин для кэша.
Есть механизмы кэширования данных. |
Расширяемость (дорабатываемость) системы.
|
Предусмотрена расширяемость с помощью плагинов. |
| Публикация событий об изменении контента | Да. |
| Возможность генерации API по созданной модели | Встроенный GraphQL браузер. |
| Ролевая модель пользователей и API | Есть различные роли и можно добавлять свои: |
| Мультитенантность | Материалы про настройку:
|
6. UI систем и примеры моделирования
Squidex
Панель управления Squidex включает два ключевых раздела:

Работа с созданием структуры данных проводится в разделе «Sсhemas», как выглядит управление данными в этом разделе можно посмотреть на скрине ниже:

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

Особенность, которую не обнаружили в других CMS, тип данных Components — позволяет к одному блоку привязать сразу несколько несколько схем данных.
Например, можно настроить заполнение в одном месте всех групп, в состав которых входит продукт. При этом может заполняться либо одна группа, либо другая, либо обе, в зависимости от кейса.

На этапе внесения сотрудник выбирает — о какой из сущностей хочет внести информацию в данный момент:

При этом сущности Category и Group могут иметь различный атрибутивный состав:

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

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

Удобно вносить текстовые данные в «MarkDown». В редакторе можно встраивать в текст гиперссылки, списки и т. п. И сразу просматривать результат:

Что касается моделирования сложной структуры данных, инструмент позволяет моделировать данные даже для прайс-листов. Например:

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

Наш компонент в разделе «Sсhemas» имеет следующую структуру:

{ "id": "6a2abfe1-cf0c-4453-b449-3886171668c5", "created": { "value": "2023-06-21T06:05:12.000Z" }, "createdBy": "subject:6437d117ed1a95c0fc81c021", "lastModified": { "value": "2023-06-22T05:03:11.000Z" }, "lastModifiedBy": "subject:6437d117ed1a95c0fc81c021", "version": { "value": "10" }, "status": "Published", "statusColor": "#4bb958", "scheduleJob": null, "isDeleted": false, "data": { "title": { "iv": "МТС Music" }, "slug": { "iv": "mts-music" }, "channel": { "iv": [ "323377a9-c720-43a4-aab0-7df9b7ad4f65" ] }, "region": { "iv": null }, "validFrom": { "iv": "2023-05-20T00:00:00Z" }, "validTo": { "iv": "9999-12-31T00:00:00Z" }, "icon": { "iv": [ "299224cf-20e5-4936-9ad5-073721ce7938" ] }, "mainImage": { "iv": [ "e0fa12c6-ddcb-48c3-ae95-15a9afa2c92a" ] }, "otherMedia": { "iv": null }, "description": { "iv": "Персональные подборки под любое настроение в приложении МТС Music" }, "shortDescription": { "iv": "Месяц музыки бесплатно без рекламы" }, "addInformation": { "iv": [ { "schemaId": "0b417452-e2df-486f-8f92-09aae9ad2d03", "title": "Почему стоит подключить:", "text": "*Два месяца бесплатно\n* Без рекламы\n* Можно скачивать и слушать офлайн\n* Персональные рекомендации\n* Бесплатный трафик для абонентов МТС\n* Более 65 млн треков в высоком качестве" } ] }, "productSpecId": { "iv": "93c20eac-e70b-4364-9626-fdf36148745e" }, "advantages": { "iv": [ { "schemaId": "a518c845-f85f-4342-9e71-675d4f6a7ad0", "title": "Выбирайте готовый плейлист", "description": "В дороге, дома, на работе или тренировке", "icon": null, "image": [ "4036fcb7-e4aa-496f-a60c-eb502d036982" ] }, { "schemaId": "a518c845-f85f-4342-9e71-675d4f6a7ad0", "title": "Детский режим", "description": "С аудиосказками, песнями и подборками из мультфильмов", "icon": null, "image": [ "70debf41-5106-47d7-871c-057ac378e4eb" ] } ] }, "faq": { "iv": [ { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Если у меня уже была подписка МТС Music, будет ли доступено два месяца бесплатно?\n ", "answer": "Нет. Предложение доступно только новым пользователям, которые никогда не подключали платную подписку МТС Music." }, { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Зачем подключать подписку МТС Music?\n ", "answer": "По подписке вы получаете полный доступ ко всему функционалу приложения и сайта, в том числе к поиску и офлайн-режиму прослушивания музыки." }, { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Что будет, если отключить подписку в пробный период?\n ", "answer": "При отключении услуги до истечения 30 дней и повторном её подключении услуга будет предоставляться на платной основе, бесплатные дни предоставляться не будут.\n\nПосле отключения платной подписки прослушивание своих сохранённых треков и плейлистов в режиме офлайн становится недоступным." }, { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Сколько будет стоить подписка после двух месяцев бесплатного доступа?\n ", "answer": "169 рублей в месяц." }, { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Как оплачивать МТС Music после пробного периода?\n ", "answer": "Для абонентов ПАО «МТС» списание средств за подписку будет производиться с лицевого счёта абонента.\n\nАбоненты других операторов мобильной связи смогут оплатить подписку, привязав банковскую карту с помощью сервиса МТС Деньги, который будет открываться непосредственно в приложении МТС Music – дополнительная авторизация не потребуется. Списания будут производиться с БК в соответствии с графиком списания подключённой услуги, безакцептно. История списаний за пользование сервисом будет отображаться в истории платежей по банковской карте абонента. Управлять подпиской пользователь сможет в приложении МТС Music, в разделе «Моя музыка» —> «Профиль»." }, { "schemaId": "f51d088d-6758-41c5-9d5a-674a5786a899", "question": "Условия использования", "answer": "*Если в течение 30 дней пробного бесплатного периода вы не пользовались сервисом, услуга будет предоставляться на платной основе, бесплатные дни предоставляться не будут.\n\n* Под «первые 30 дней для новых пользователей в подарок» понимается скидка в размере 100% стоимости первых по времени 30 дней пользования сервисом.\n\n* Подписка продлевается автоматически на месяц, если автопродление не отключено до окончания текущего периода, до 24:00. Неиспользованная часть бесплатного пробного периода аннулируется после приобретения подписки. Вы можете управлять своими подписками после покупки и отключить автопродление в настройках своей учётной записи.\n\n* Обращаем ваше внимание, что для онлайн-прослушивания музыки необходимо наличие доступа к сети интернет. В случае если включённая в основной и дополнительный пакет квота интернет-трафика будет превышена, вы сможете прослушивать только сохранённые в приложении композиции, онлайн-прослушивание музыки будет недоступно.\n\n* Бесплатный интернет-трафик при прослушивании музыки в приложении МТС Music не тарифицируется только для абонентов МТС.\n\n* Бесплатный интернет-трафик предоставляется только при прослушивании музыки в приложении МТС Music, загрузка прочего содержимого оплачивается согласно условиям тарифного плана.\n\n* Сервис доступен абонентам сети мобильной связи любого оператора на всей территории Российской Федерации и предназначен для смартфонов и планшетов на базе операционных систем Android (4.1 и выше), iOS (7.0 и выше), а также ПК.\n\n* Услугу предоставляет ПАО «МТС» при поддержке ООО «Стрим» и ООО «Яндекс.Медиасервисы».\n\n* Все цены указаны с учётом НДС." } ] }, "price": { "iv": [ { "schemaId": "7766d9e4-5d1a-4853-8ff3-0896544b2851", "currentPrice": "0", "oldPrice": "169", "unit": [ "c229c4a8-2d3e-4634-9ccc-45778b357193" ], "title": "Триальный период", "shortDescription": "30 дней бесплатно, далее 169 ₽/мес", "description": null } ] } }, "schemaName": "contentspecifiction", "schemaDisplayName": "contentspecifiction", "referenceFields": [ { "fieldId": 1, "name": "title", "properties": { "isRequired": false, "isRequiredOnPublish": false, "isHalfWidth": false, "fieldType": "String", "createEnum": false, "editor": "Input", "inlineEditable": false, "isEmbeddable": false, "isUnique": false, "contentType": "Unspecified", "label": "Наименование" }, "isLocked": false, "isHidden": false, "isDisabled": false, "_links": {}, "canAddField": false, "canDelete": false, "canDisable": false, "canEnable": false, "canOrderFields": false, "canHide": false, "canLock": false, "canShow": false, "canUpdate": false, "partitioning": "invariant", "nested": [] } ], "_links": { "self": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5", "method": "GET" }, "previous": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5/9", "method": "GET" }, "draft/create": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5/draft", "method": "POST" }, "status/Archived": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5/status", "method": "PUT", "metadata": "#eb3142" }, "status/Draft": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5/status", "method": "PUT", "metadata": "#8091a5" }, "delete": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5", "method": "DELETE" }, "patch": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5", "method": "PATCH" }, "update": { "href": "/api/content/mts/contentspecifiction/6a2abfe1-cf0c-4453-b449-3886171668c5", "method": "PUT" } }, "canDelete": true, "canDraftCreate": true, "canDraftDelete": false, "canCancelStatus": false, "canUpdate": true, "statusUpdates": [ { "status": "Archived", "color": "#eb3142" }, { "status": "Draft", "color": "#8091a5" } ] }
А вот пример запроса и ответа в GraphQL API.
{ queryContentspecifictionContents( filter: "data/productSpecId/iv eq '93c20eac-e70b-4364-9626-fdf36148745e' and status eq 'Published' and data/channel/iv eq '323377a9-c720-43a4-aab0-7df9b7ad4f65' and data/validFrom/iv gt 2023-05-19T00:00:00Z" ) { id status version flatData { title validFrom validTo productSpecId channel { id ... on Channel { flatData { externalid title } } } description shortDescription addInformation { title text { text } } advantages { title description icon { type metadata url } } icon { type metadata url tags } mainImage { type metadata url tags } otherMedia { type metadata url tags } faq { question { text } answer { text } } price { title description shortDescription oldPrice currentPrice unit { id flatData { title alias titleInGenitiveCase fullTitle } } } } } }
{{ "data": { "queryContentspecifictionContents": [ { "id": "6a2abfe1-cf0c-4453-b449-3886171668c5", "status": "PUBLISHED", "version": 10, "flatData": { "title": "МТС Music", "validFrom": "2023-05-20T00:00:00Z", "validTo": "9999-12-31T00:00:00Z", "productSpecId": "93c20eac-e70b-4364-9626-fdf36148745e", "channel": [ { "id": "323377a9-c720-43a4-aab0-7df9b7ad4f65", "flatData": { "externalid": "741ba712-3069-48e3-928c-8631e5ed186e", "title": "Personal" } } ], "description": "Персональные подборки под любое настроение в приложении МТС Music", "shortDescription": "Месяц музыки бесплатно без рекламы", "addInformation": [ { "title": "Почему стоит подключить:", "text": { "text": "*Два месяца бесплатно\n* Без рекламы\n* Можно скачивать и слушать офлайн\n* Персональные рекомендации\n* Бесплатный трафик для абонентов МТС\n* Более 65 млн треков в высоком качестве" } } ], "advantages": [ { "title": "Выбирайте готовый плейлист", "description": "В дороге, дома, на работе или тренировке", "icon": null }, { "title": "Детский режим", "description": "С аудиосказками, песнями и подборками из мультфильмов", "icon": null } ], "icon": [ { "type": "UNKNOWN", "metadata": {}, "url": "http://127.0.0.1/api/assets/mts/299224cf-20e5-4936-9ad5-073721ce7938/", "tags": [ "type/svg", "image" ] } ], "mainImage": [ { "type": "IMAGE", "metadata": { "pixelWidth": 934, "pixelHeight": 937, "imageQuality": 100, "description": "JFIF File" }, "url": "http://127.0.0.1/api/assets/mts/e0fa12c6-ddcb-48c3-ae95-15a9afa2c92a/", "tags": [ "type/jpg", "image", "image/medium" ] } ], "otherMedia": null, "faq": [ { "question": { "text": "Если у меня уже была подписка МТС Music, будет ли доступено два месяца бесплатно?\n " }, "answer": { "text": "Нет. Предложение доступно только новым пользователям, которые никогда не подключали платную подписку МТС Music." } }, { "question": { "text": "Зачем подключать подписку МТС Music?\n " }, "answer": { "text": "По подписке вы получаете полный доступ ко всему функционалу приложения и сайта, в том числе к поиску и офлайн-режиму прослушивания музыки." } }, { "question": { "text": "Что будет, если отключить подписку в пробный период?\n " }, "answer": { "text": "При отключении услуги до истечения 30 дней и повторном её подключении услуга будет предоставляться на платной основе, бесплатные дни предоставляться не будут.\n\nПосле отключения платной подписки прослушивание своих сохранённых треков и плейлистов в режиме офлайн становится недоступным." } }, { "question": { "text": "Сколько будет стоить подписка после двух месяцев бесплатного доступа?\n " }, "answer": { "text": "169 рублей в месяц." } }, { "question": { "text": "Как оплачивать МТС Music после пробного периода?\n " }, "answer": { "text": "Для абонентов ПАО «МТС» списание средств за подписку будет производиться с лицевого счёта абонента.\n\nАбоненты других операторов мобильной связи смогут оплатить подписку, привязав банковскую карту с помощью сервиса МТС Деньги, который будет открываться непосредственно в приложении МТС Music – дополнительная авторизация не потребуется. Списания будут производиться с БК в соответствии с графиком списания подключённой услуги, безакцептно. История списаний за пользование сервисом будет отображаться в истории платежей по банковской карте абонента. Управлять подпиской пользователь сможет в приложении МТС Music, в разделе «Моя музыка» —> «Профиль»." } }, { "question": { "text": "Условия использования" }, "answer": { "text": "*Если в течение 30 дней пробного бесплатного периода вы не пользовались сервисом, услуга будет предоставляться на платной основе, бесплатные дни предоставляться не будут.\n\n* Под «первые 30 дней для новых пользователей в подарок» понимается скидка в размере 100% стоимости первых по времени 30 дней пользования сервисом.\n\n* Подписка продлевается автоматически на месяц, если автопродление не отключено до окончания текущего периода, до 24:00. Неиспользованная часть бесплатного пробного периода аннулируется после приобретения подписки. Вы можете управлять своими подписками после покупки и отключить автопродление в настройках своей учётной записи.\n\n* Обращаем ваше внимание, что для онлайн-прослушивания музыки необходимо наличие доступа к сети интернет. В случае если включённая в основной и дополнительный пакет квота интернет-трафика будет превышена, вы сможете прослушивать только сохранённые в приложении композиции, онлайн-прослушивание музыки будет недоступно.\n\n* Бесплатный интернет-трафик при прослушивании музыки в приложении МТС Music не тарифицируется только для абонентов МТС.\n\n* Бесплатный интернет-трафик предоставляется только при прослушивании музыки в приложении МТС Music, загрузка прочего содержимого оплачивается согласно условиям тарифного плана.\n\n* Сервис доступен абонентам сети мобильной связи любого оператора на всей территории Российской Федерации и предназначен для смартфонов и планшетов на базе операционных систем Android (4.1 и выше), iOS (7.0 и выше), а также ПК.\n\n* Услугу предоставляет ПАО «МТС» при поддержке ООО «Стрим» и ООО «Яндекс.Медиасервисы».\n\n* Все цены указаны с учётом НДС." } } ], "price": [ { "title": "Триальный период", "description": null, "shortDescription": "30 дней бесплатно, далее 169 ₽/мес", "oldPrice": "169", "currentPrice": "0", "unit": [ { "id": "c229c4a8-2d3e-4634-9ccc-45778b357193", "flatData": { "title": "₽/мес", "alias": null, "titleInGenitiveCase": "рублей в месяц", "fullTitle": null } } ] } ] } } ] }, "extensions": { "tracing": { "version": 1, "startTime": "2023-06-26T05:20:49.9570693Z", "endTime": "2023-06-26T05:20:50.0001375Z", "duration": 43068200, "parsing": { "startOffset": 1100, "duration": 43300 }, "validation": { "startOffset": 45100, "duration": 1028900 }, "execution": { "resolvers": [] } } } } }
Strapi
А теперь посмотрим, как выглядит Strapi.
Панель управления:

Ключевыми разделами Strapi CMS являются:
- Content-Type Builder — инструмент создания объектов, который позволяет создавать таблицы для хранения данных и связывать их между собой, а также настраивать их отображение (порядок полей при заполнении и прочее) для пользователя;
- Сontet Manager — раздел для заполнения созданных объектов данными.
С чем ведется работа в Content-Type Builder:
- коллекции «COLLECTION TYPES» — набор данных разных типов, который может включать множество записей;
- компоненты — объект данных, упрощающий внесение данных в коллекции. Например, когда нужно создать подряд несколько однотипных записей внутри коллекции;
- диночные типы «SINGLE TYPES» — набор данных разных типов. В отличие от коллекции может включать только одну запись. Полезно для создания простых страниц. Например, для создания раздела «Контакты» на сайте.

Подробнее про создание объектов в Strapi CMS можно почитать тут.
Наполнять контент можно данными следующих типов:


В отличии от Squidex нельзя настроить отдельное наименование поля и подсказку для отображения пользователю при внесении:

Гораздо меньше настроек по валидации и формату ввода данных (также на примере текстового поля):

Моделирование сложных структур данных и данных с несколькими элементами в составе производится с помощью компонентов (как и в Squidex):

Что касается моделирования сложной структуры данных, рассмотрим их заведение (как и для Squidex) на этом примере:

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

Наш компонент имеет следующую структуру:

В отличие от Squidex на этом экране нет функции перетаскивания и нельзя изменить очередность заполнения полей и компонентов на форме.
Есть кнопка конфигурирования представления

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

Так будет выглядеть внесение информации в разделе «Сontet Manage» UI Strapi для первого элемента данных:
Поэтому не повторяйте наших ошибок, следите, чтобы поле «title» всегда шло первым, если используете данную CMS.

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

Ниже можно посмотреть, как будет выглядеть данная информация в GraphQL API.
query { tariffs( filters: { tp: { title: { eq: "Тарифище" } } and: [ { region: { title: { eq: "Краснодар" } } } { vaidFrom: { gte: "2010-08-25T10:15:30Z" } } { validTo: { lte: "2050-08-25T10:15:30Z" } } ] } ) { data { id attributes { detailInformation { group { data { attributes { title iconURL } } } sub_gr { data { attributes { title slug } } } title { data { attributes { slug title } } } value unit { data { attributes { title slug } } } } } } } }
{ "data": { "tariffs": { "data": [ { "id": "6", "attributes": { "detailInformation": [ { "group": { "data": { "attributes": { "title": "SMS и MMS, за сообщение", "iconURL": "//contents.mts.ru/b-icon_envelope.svg" } } }, "sub_gr": { "data": { "attributes": { "title": "В пределах включенного пакета SMS", "slug": "SMS-v-predelah-vklyuchennogo-paketa" } } }, "title": { "data": { "attributes": { "slug": "SMSRussiaOperators", "title": "SMS на номера любых операторов России" } } }, "value": "3.70", "unit": { "data": { "attributes": { "title": "₽ за сообщение", "slug": "rub-msg" } } } } ] } } ] } } }
Orchard Core
В Orchard Core столкнулись с ограничениями в моделировании данных и прочими сложностями, которые представлены в сравнительном анализе (таблица выше). Поэтому покажем только базовые элементы интерфейса. Примеры моделирования данных будут приведены только для Strapi и Squidex.

В основном работа ведется с Типами (Parts) и Частям контента.

Части контента — это что-то вроде компонентов в других системах:

Подробнее вопрос терминологии системы раскрывается тут.
Можно встроить в контент следующие типы данных:

Перечень доступных настроек очень ограничен.

7. Заключение
Выбор и применение современных CMS является важным вопросом для команд, которые хотят эффективно управлять контентом на различных платформах. Решение в каждом случае необходимо принимать исходя из собственных потребностей и ИТ-ландшафта.
Сводная таблица со сравнением CMS по ключевым для нашей команды критериям.
| Критерий | Strapi CMS | Squidex | Orchard Core |
| Сообщество/поддержка | Большое, частые обновления | Среднее, тесное взаимодействие с пользователями | Среднее, поддержка .NET Foundation |
| Open source решение | ![]() |
![]() |
![]() |
Стек:
|
Angular + Node.js (JS/TypeScript) | Angular (TypeScript) + C# | JS + ASP.NET Core |
| СУБД | SQL (PostgreSQL, MySQL/MariaDB, SQLite) | NoSQL (MongoDB) | SQL (SQL Server, MySQL, PostgreSQL, SQLite) |
| Удобство использования | Среднее | Высокое | Низкое |
| Контроль над ошибками в UI и возможность «сломать» систему | Низкий | Высокий | Средний |
| Гибкость системы при моделировании данных | Средняя | Высокая | Низкая |
| Поддержка GraphQL API | С помощью плагина GraphQL | Strapi Market |
![]() |
![]() |
| Наличие локализации | ![]() |
![]() |
![]() |
| Поддержка версионирования | Есть плагин |
![]() |
Через модуль |
| Возможность управления flow | Есть плагин |
![]() |
![]() |
| Импорт контента из внешних источников | Есть плагин |
![]() |
![]() |
| Хранение бинарных файлов (assets)/мультимедиа (S3 compatible) или интеграция с такой системой | ![]() |
![]() |
![]() |
| Расширяемость системы | Есть свой магазин плагинов |
Предусмотрена расширяемость с помощью плагинов |
Предусмотрена расширяемость с помощью плагинов |
| Публикация событий об изменении контента | ![]() |
![]() |
![]() |
| Ролевая модель пользователей и API | ![]() |
![]() |
![]() |
| Мультитенантность из коробки | ![]() |
![]() |
![]() |
— решение из коробки соответствует критерию/поддерживает данный функционал.
— решается частично либо с установкой расширений/плагинов.
— отсутствует.
По результатам пилотных задач на наш взгляд самой удобной оказалась CMS Squidex, как при моделировании схемы данных, так и при её наполнении.
В Strapi постоянно сталкивались с различными багами. Есть замечания к пользовательскому интерфейсу, не все операции интуитивны и понятных даже для специалистов с опытом работы с другими CMS.
В UI Orchard Core были большие сложности с моделированием контента. В CMS не оказалось ряда критичных для нас функций (к которым мы уже привыкли после Strapi и Squidex), например, создание нескольких экземпляров одного компонента при внесении контента или возможность вложить компонент в компонент.
У Squidex интуитивно понятный UI, гибкие возможности по созданию модели данных. Мы не столкнулись с какими-либо ограничениями при моделировании.
Это решение отвечает всем исходным требованиям, которые мы предъявляли к Headless CMS.
Из-за особенностей предметной области у нас есть дополнительные требования по регионализации и версионированию контента, которые не поддерживаются ни одной из систем, но базовая функциональность и стек Squidex являются хорошей основной для последующей кастомизации и доработок.
Будем рады, если статья оказалась вам полезной. В комментариях поделитесь, интересны ли вам другие возможности CMS или, возможно, хотелось бы поподробнее узнать про какую-то функциональность. Если тема будет интересна, обязательно расскажем подробнее в будущих статьях.
CloudMTS поможет гибко управлять и разворачивать системы любого масштаба: от сайтов-визиток и простых CMS до высоконагруженных e-commerce-проектов. Сервис позволяет быстро выстраивать отказоустойчивую систему и масштабировать виртуальные машины под разный уровень нагрузки.
ссылка на оригинал статьи https://habr.com/ru/articles/750694/
Есть, можно настроить скрытие определенных полей в API.
История запросов GraphQL пользователя (playground) хранится в локальном storage браузера.


Есть плагин 




Добавить комментарий