Drupal как headless CMS: настройка без ловушек
JSON:API в Drupal позволяет отделить контент от интерфейса, но одного включения модуля недостаточно. Разбираем настройку схемы данных, доступов, CORS, кеширования и проверок, которые стоит пройти до подключения фронтенда.

Drupal можно превратить в headless CMS за один рабочий день: редакторы продолжают управлять материалами в админке, а сайт, мобильное приложение или витрина получают данные через JSON:API. Но проект ломается не на запросе к /jsonapi, а раньше — из-за неправильной модели контента, открытых разрешений, неограниченного CORS или URL, привязанного к конкретной структуре сайта.
Что должно получиться
Ниже — инструкция для Drupal 10.x и 11.x с включённым модулем JSON:API. В конце у вас будет отдельный фронтенд, который читает опубликованные материалы из Drupal по HTTP, а редактор сможет менять контент без правок в коде.
Для старта нужны установленный Drupal 10.x или 11.x, права администратора, домен CMS, отдельный адрес фронтенда и HTTPS. Если Drupal уже работает, проверьте также версию PHP и базу данных по официальным требованиям вашей ветки. Команды установки здесь не приводятся: они зависят от способа размещения — Composer, готовый образ, хостинг или managed-платформа.
Шаг 1. Спроектируйте данные до включения API
Headless Drupal не отдаёт «страницу как она выглядит в админке». Он отдаёт сущности: материалы, пользователей, файлы, термины таксономии и поля.
- Создайте тип материала. Например, Article для публикаций. Добавьте поля с понятными машинными именами:
field_lead,field_image,field_author,field_tags. - Разделите обязательный и необязательный контент. Заголовок, дата публикации и основной текст обычно обязательны. Подзаголовок, галерея или цитата могут быть пустыми.
- Определите состояние публикации. Фронтенд должен показывать только опубликованные материалы, если вы специально не строите предпросмотр для редакторов.
- Заранее договоритесь о форматах. Например, изображения должны приходить с URL файла, альтернативным текстом и размерами, а не как HTML, который фронтенд пытается разобрать самостоятельно.
Проверка. Создайте тестовый материал и откройте его в админке. У него должны быть заполнены только те поля, которые действительно нужны интерфейсу. Если фронтенд будет зависеть от десяти необязательных полей, проблема появится уже при первом неполном материале.
Сноска. Сущность в Drupal — объект, которым система управляет как отдельной записью: материал, пользователь, файл или термин таксономии. Поля принадлежат сущности и становятся частью ответа API.
Шаг 2. Включите JSON:API и проверьте маршрут
JSON:API входит в ядро Drupal 10.x и 11.x. Для чтения материалов обычно не требуется писать собственный контроллер или устанавливать отдельный модуль.
- Откройте раздел управления расширениями и включите модуль JSON:API. Если он уже активен, переходите дальше.
- Откройте в браузере адрес
https://cms.example.com/jsonapi. Вместоcms.example.comподставьте адрес Drupal. - Найдите в ответе ресурс типа
node--article. Его коллекция обычно доступна по адресу/jsonapi/node/article. - Проверьте конкретный материал через фильтр по UUID. UUID можно посмотреть в ответе коллекции или в данных сущности.
curl -H "Accept: application/vnd.api+json" \
"https://cms.example.com/jsonapi/node/article?page[limit]=10"
В запросе используется версия медиа-типа JSON:API, которую ожидает Drupal. Для производственного фронтенда адрес CMS лучше хранить в переменной окружения, а не зашивать в исходники.
Проверка. В ответе должна появиться JSON-структура с массивом data. У каждого элемента будут как минимум type, id и attributes. Если коллекция пустая, сначала проверьте, что тестовый материал опубликован.
Шаг 3. Ограничьте ответ до нужных полей
Первый запрос часто возвращает больше данных, чем нужно карточке или странице. Это не только лишний трафик: структура ответа JSON:API становится частью договорённости между CMS и фронтендом, и её труднее менять без последствий.
Для списка материалов используйте параметры fields и include. В примере ниже запрашиваются только поля материала и связанные изображения. Имена полей нужно заменить на те, которые есть в вашей конфигурации Drupal.
curl -H "Accept: application/vnd.api+json" \
"https://cms.example.com/jsonapi/node/article?fields[node--article]=title,created,field_lead,field_image&include=field_image&page[limit]=10"
Связанные сущности приходят в массиве included. Фронтенд должен уметь находить нужный файл по ссылкам из поля связи, а не рассчитывать, что изображение всегда лежит в одном фиксированном месте.
Проверка. Сравните размер ответа с запросом без fields. В ответе должны остаться только запрошенные атрибуты, а изображение — появиться в included, если материал действительно содержит такую связь.
Шаг 4. Настройте доступы, авторизацию и CORS
Для публичных опубликованных материалов обычно нужен анонимный доступ на чтение. Доступ к черновикам, пользователям, заказам и административным сущностям должен оставаться закрытым.
- Создайте отдельную роль для редакторов и не выдавайте ей административные права без необходимости.
- Проверьте разрешения анонимного пользователя. Разрешайте только то чтение, которое нужно публичному сайту.
- Откройте JSON:API в режиме анонимного пользователя в приватном окне браузера. Так вы увидите реальную публичную поверхность, а не результат своей администраторской сессии.
- Если CMS и фронтенд находятся на разных доменах, разрешите CORS только для точного origin фронтенда, например
https://frontend.example.com. Не используйте универсальное разрешение для всех доменов на рабочем сайте. - После изменения серверной конфигурации очистите кеш Drupal и проверьте preflight-запрос браузера. CORS должен разрешать конкретные методы и заголовки, которые действительно использует клиент.
Настройки CORS зависят от версии Drupal и способа размещения. Их нужно вносить в конфигурацию сервисов по документации вашей версии, а не копировать пример из старого проекта. Отдельно настройте HTTPS и заголовки прокси: ошибка на этом уровне часто выглядит для разработчика как «API не работает».
Проверка. Запрос с разрешённого домена получает ответ, а запрос с постороннего origin блокируется браузером. При этом прямой вызов через curl может показать данные даже при ошибочном CORS: curl не применяет браузерную политику источников.
В headless-проекте API — это контракт между редактором и интерфейсом. Если не зафиксировать этот контракт до разработки фронтенда, каждое новое поле превращается в отдельную интеграционную поломку.
Шаг 5. Подключите фронтенд без привязки к внутренностям Drupal
Фронтенд должен знать публичный URL ресурса и правила преобразования данных, но не должен собирать адреса из внутренних имён таблиц, путей файлов или предположений о порядке полей.
Для списка материалов достаточно обычного HTTP-клиента. Если вы пишете интерфейс на JavaScript, обработайте как минимум статус ответа, отсутствие data, пустую коллекцию и недоступное изображение. Кеширование ответа и стратегию повторных запросов выбирайте на стороне фронтенда или CDN — это отдельный слой, а не функция JSON:API.
Для страниц материалов используйте UUID или другой стабильный идентификатор. Не стройте постоянные ссылки только на внутреннем числовом ID, если URL должен пережить миграцию или изменение маршрутов.
Проверка. Создайте материал, измените его заголовок в Drupal и обновите страницу фронтенда. Новое значение должно появиться без пересборки приложения, если публикация не проходит через отдельный статический кеш.
Если не получилось
- 404 Not Found на
/jsonapi/node/article. Проверьте, что включён JSON:API, тип материала действительно называется Article, а URL не изменён настройками маршрутов или прокси. - 403 Forbidden. Запрос выполняется без нужного разрешения. Проверьте его в приватном окне и не путайте права администратора с правами анонимного пользователя.
- В браузере сообщение про CORS policy. Уточните точный origin фронтенда: протокол, домен и порт считаются частью значения. Проверьте также OPTIONS-запрос и конфигурацию обратного прокси.
- Ответ пустой, хотя материал есть. Скорее всего, материал не опубликован, попал под фильтр или вы обращаетесь не к тому типу ресурса. Сначала уберите фильтры и проверьте коллекцию.
- Картинка не отображается. Проверьте связь
field_image, параметрinclude, права на файл и значение URI. Не подставляйте URL вручную из имени файла.
Где подход ломается
JSON:API хорошо подходит для публикационного контента и каталогов, но не решает автоматически предпросмотр черновиков, сложные транзакции, поиск по бизнес-правилам и потоковую доставку событий. Для таких задач может понадобиться отдельная схема авторизации, поисковый сервис, GraphQL или собственный API-слой. Выбирать замену стоит после измерения требований, а не потому, что стандартный ответ JSON:API кажется большим.
Ещё одна граница — кеширование. Drupal, reverse proxy, CDN и фронтенд могут хранить разные версии материала. Инвалидация кеша — отдельная тема; здесь важно лишь заранее решить, сколько времени опубликованное изменение может не отображаться и кто отвечает за очистку каждого слоя.
Что проверить перед запуском
- На публичном домене не видны черновики и административные сущности.
- Ответы коллекций ограничены пагинацией, а не отдают весь архив одним запросом.
- Для связанных файлов настроены права и проверена выдача изображений.
- CORS разрешает только нужные домены и методы.
- Фронтенд корректно обрабатывает 403, 404, пустой список и временную ошибку CMS.
- В логах и мониторинге есть время ответа API, доля ошибок и размер ответа.
Что делать дальше
После первого успешного запроса зафиксируйте схему ресурсов: типы, поля, связи, обязательность и пример ответа. Затем добавьте тестовый набор из опубликованного, пустого и удалённого материала. В продакшене смотрите не только на доступность Drupal, но и на p95 времени ответа JSON:API, количество запросов на страницу и долю ответов 4xx и 5xx. Именно эти показатели покажут, стала ли headless-связка рабочей системой, а не просто включённым модулем.
Контент-конвейер: Из одной идеи — текст, изображение, озвучка и ролик. Один заказ вместо четырёх.
Спросить за 60 ₽Источники: JSON:API module — официальная документация Drupal, Decoupled Drupal — официальная документация Drupal
Частые вопросы
Можно ли использовать Drupal как headless CMS без отдельного backend-разработчика?
Нужно ли устанавливать отдельный модуль для JSON:API?
Почему запрос к JSON:API возвращает 403, хотя я администратор?
Что делать, если фронтенд не видит API из-за CORS?
Подойдёт ли JSON:API для интернет-магазина на Drupal?
Как понять, что headless-связка готова к продакшену?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.