Обновим Strapi 4 до 5
Strapi 4 больше не обновляется: багфиксы прекратились в конце октября 2025, патчи безопасности в конце апреля 2026. Всё, что найдут в ветке 4.x после этого, останется незакрытым. Обновление до Strapi 5 не сводится к одной команде: меняется формат ответа API, идентификаторы, серверный API для своего кода и вся система плагинов. Мы ведём сайты на Strapi 4 и 5 и ниже расписали, что именно ломается, как мы проводим обновление и сколько это занимает.
Что случилось с поддержкой Strapi 4
По официальному графику Strapi:
| Дата | Что произошло |
|---|---|
| 24 сентября 2024 | Вышел Strapi 5 |
| Конец октября 2025 | Прекратились багфиксы для Strapi 4, включая критические |
| Конец апреля 2026 | Прекратились патчи безопасности. Strapi 4 в статусе end of life |
Для владельца сайта это значит: сервер с админкой, куда заходят сотрудники и куда загружаются файлы, работает на ПО, в котором уязвимости больше не закрывают. Речь не только о самом Strapi, но и о его зависимостях (Koa, React, библиотеки загрузки файлов), которые в ветке 4.x тоже заморожены.
Что ломается при переходе на Strapi 5
Это список из официального перечня breaking changes, отсортированный по тому, что чаще всего стреляет на реальных проектах.
1. Формат ответа REST API
В Strapi 4 каждая запись была завёрнута в data.attributes, в Strapi 5 поля лежат в корне объекта:
// Strapi 4
{ "data": { "id": 14, "attributes": { "title": "Статья", "category": { "data": { "id": 3, "attributes": { "name": "Новости" } } } } } }
// Strapi 5
{ "data": { "documentId": "clkgylmcc000008lcdd868feh", "title": "Статья", "category": { "documentId": "clkgylw7d000108lc4rw1bb6s", "name": "Новости" } } }Ломается весь фронт, который читает attributes. Переходный режим: заголовок Strapi-Response-Format: v4 в запросе возвращает старую обёртку. Для GraphQL то же самое делает настройка v4CompatibilityMode: true в конфиге плагина. Мы включаем совместимость на время обновления и снимаем её по одному эндпоинту, когда фронт переписан.
2. documentId вместо id
Числовой id в API заменён строковым documentId. Все ссылки вида /api/articles/14 перестают работать, нужен /api/articles/clkgylmcc000008lcdd868feh. Сохранённые где-то во внешних системах числовые id (в CRM, в приложении, в старых ссылках) придётся сопоставлять. Сортировка по id больше не гарантирует хронологию, сортируйте по createdAt.
3. Entity Service заменён на Document Service
Весь свой серверный код (контроллеры, сервисы, крон, lifecycle-хуки) на strapi.entityService нужно переписать на strapi.documents():
// Strapi 4
await strapi.entityService.findOne('api::article.article', id, { populate: ['cover'] });
await strapi.entityService.findMany('api::article.article', { publicationState: 'preview' });
// Strapi 5
await strapi.documents('api::article.article').findOne({ documentId, populate: ['cover'] });
await strapi.documents('api::article.article').findMany({ status: 'draft' });Кодмод делает замену автоматически, но там, где раньше передавался числовой id, оставляет метку __TODO__, и каждое такое место нужно разобрать руками. Параметр publicationState стал status, вместо записи publishedAt появились методы publish() и unpublish().
4. Плагины
Плагины Strapi 4 в Strapi 5 не работают. Причины: новый Plugin SDK, удалённый @strapi/helper-plugin (импорты переезжают в @strapi/strapi/admin), Design System v2, сборка админки на Vite вместо webpack. Для каждого стороннего плагина три варианта: автор уже выпустил версию для v5, есть замена, или переписываем сами. На типовом сайте обычно 2–4 сторонних плагина, и хотя бы один из них оказывается в третьей категории.
5. Кастомизация админки
Если в src/admin есть свои компоненты, страницы или webpack.config.js, всё это переезжает на Vite: конфиг vite.config, файлы с JSX переименовываются в .jsx или .tsx, алиасы webpack удалены. Есть флаг --bundler=webpack, но это костыль с предупреждением в консоли.
6. База данных и окружение
- Node.js: только LTS 22, 24, 26. Сервера на Node 18 и 20 обновляем.
- MySQL 5 не поддерживается, минимум MySQL 8. Клиент только
mysql2. - SQLite: только
better-sqlite3. - Настройки S3-провайдера переезжают в
s3Options, кодмод это делает. - Уровень логов по умолчанию стал
http, часть настроек переехала из переменных окружения вconfig/server.
7. Populate, Draft & Publish, i18n
- Populate для dynamic zone требует явного описания через
on:populate[sections][on][sections.hero][populate][0]=image. Запросы, которые в v4 работали сpopulate=deepиз плагина, переписываются. У нас на сайте с динамическими секциями это заняло отдельный день. - Draft & Publish: у каждой записи теперь есть черновик и опубликованная версия под одним
documentId, а не две записи. - Плагин i18n удалён, мультиязычность в ядре. Локали одной записи делят один
documentId. - Зарезервированные имена: поле нельзя назвать
status,locale,localizations,meta,document,entryId,then, а имена полей и моделей не могут начинаться соstrapi. Такие поля переименовывают до обновления, иначе данные потеряются. Бывают и конфликты вне официального списка: один разработчик в открытом отчёте об обновлении потерял часы на коллекцииdocuments, которая столкнулась с Document Service, и полеfilters, совпавшее с параметром запросов.
Как проходит обновление у нас
Порядок, который мы отработали на своих проектах. Боевой сервер трогаем в самом конце.
- Аудит. Смотрим версию (должна быть последняя 4.26.x, иначе сначала
npx @strapi/upgrade minor), список плагинов и их статус в маркетплейсе, объём своего кода вsrc/api,src/extensions,src/admin, кто и как ходит в API (сайт, приложение, интеграции). - Копия. Разворачиваем копию проекта с боевой базой. Контент из прода в копию переносим командой
strapi transfer, а не архивом экспорта, потому что архивы на больших медиа у нас бились. - Прогон кодмодов. На копии запускаем
npx @strapi/upgrade major. Инструмент показывает список изменений до применения, ставит зависимости Strapi 5 и правит код: Entity Service на Document Service, lifecycle-хуки, конфиг S3, зависимости React и styled-components. - Ручная работа. Ищем все
__TODO__от кодмода, переписываем контроллеры и сервисы, где был числовой id, чиним populate для dynamic zone, переносим кастомизацию админки на Vite, заменяем или переписываем плагины. - Первый запуск. При старте Strapi 5 сам прогоняет миграции базы: добавляет
documentId, перестраивает черновики и локали. После этого назад дороги нет, поэтому шаг делается на копии, а бэкап боевой базы лежит рядом. - Тест API. Прогоняем каждый эндпоинт, которым пользуется фронт и интеграции, сравниваем ответы v4 и v5. Включаем
Strapi-Response-Format: v4, если фронт будут переделывать позже. - Фронт. Переписываем чтение
data.attributes, ссылки поid, GraphQL-запросы. Если фронт на Next.js делали мы, идёт в ту же смету, если другой подрядчик, отдаём ему список изменённых эндпоинтов. - Выкатка. Обновляем Node на сервере, собираем образ Strapi 5, переключаем с бэкапом и планом отката (восстановление базы и старого образа). После выкатки две недели следим за логами.
Сроки и стоимость
У студий обычно написано "1–2 недели, цена по запросу". Мы делим проекты на три типа, у каждого своя вилка:
| Проект | Что внутри | Срок | Объём работы |
|---|---|---|---|
| Контентный сайт | Типы из конструктора, стандартные плагины, фронт читает REST | 2–5 рабочих дней | Кодмоды, проверка API, правка фронта под плоский формат |
| Сайт с логикой | Свои контроллеры и сервисы, dynamic zone, i18n, 2–4 сторонних плагина | 1–3 недели | Плюс переписывание Document Service, populate, замена плагинов |
| Проект с кастомной админкой | Свои плагины, страницы админки, webpack-конфиг, интеграции по id | 3–6 недель | Плюс переезд на Vite и Plugin SDK, сопоставление id во внешних системах |
Для ориентира: разработчик, который опубликовал подробный отчёт об обновлении сильно кастомизированного проекта, потратил около 200 часов, из них 120 на плагины и кастомизацию, по 40 на данные и фронт.
Стоимость складывается из часов по таблице. Точную сумму и срок называем через день после доступа к репозиторию, до этого не обещаем ничего, потому что кастомный код у всех разный.
Когда обновление не лучший вариант
Если фронт уже на Next.js, своей логики много, а от Strapi по сути осталась админка, стоит посчитать переезд на Payload CMS: он живёт внутри Next.js, и переезд может стоить примерно столько же, сколько обновление. Сравнение двух систем на наших проектах: headless.expert/strapi-vs-payload.
Если у вас сайт на Strapi 4, пришлите ссылку на репозиторий или просто адрес админки. Посмотрим плагины и объём кода и через день напишем, сколько займёт обновление и что в нём будет самым сложным.
Частые вопросы
Можно ли обновить Strapi 4 до 5 без переписывания фронта?
Временно да. Заголовок Strapi-Response-Format: v4 в запросах к REST возвращает старый формат с data.attributes, а для GraphQL есть настройка v4CompatibilityMode. Это переходный режим: фронт всё равно придётся переделать под плоский формат и documentId, но можно делать это по частям после обновления бэкенда.
Сколько стоит обновление Strapi 4 до 5?
Зависит от объёма своего кода: контроллеров, сервисов, плагинов, кастомизаций админки и от того, кто правит фронт. Типовой сайт без самописных плагинов у нас укладывается в несколько дней, проект с кастомной админкой и своими плагинами в несколько недель. Точную сумму называем через день после просмотра репозитория.
Что будет с плагинами при обновлении?
Плагины Strapi 4 в Strapi 5 не работают: изменился API плагинов, удалён helper-plugin, сборка админки переехала на Vite. Официальные плагины (upload, users-permissions, i18n, graphql) обновляются вместе с ядром, а сторонние нужно проверить в маркетплейсе и заменить или переписать.
Можно ли откатиться на Strapi 4 после обновления?
Автоматического отката нет. При первом запуске Strapi 5 прогоняет миграции базы, поэтому единственный путь назад это восстановить бэкап базы и старую ветку кода. Именно поэтому мы обновляем сначала копию проекта, а боевой сервер трогаем в последнюю очередь.
Нужно ли обновлять Node.js?
Да. Strapi 5 поддерживает только LTS-версии Node.js, сейчас это 22, 24 и 26. Если сервер на Node 18 или 20, обновление Node входит в работу.
Что будет, если остаться на Strapi 4?
Сайт продолжит работать, но новых исправлений не будет: багфиксы прекратились в конце октября 2025, патчи безопасности в конце апреля 2026. Каждая следующая найденная уязвимость в Strapi 4 или его зависимостях останется открытой навсегда, пока вы не обновитесь.