Payload и опыт взаимодействия с ним
Привет! Меня зовут Сергей, я ведущий разработчик в Lad. В этой статье речь пойдет об опыте работы с Payload.
В нашей компании мы использовали Payload для создания быстрых прототипов и MVP-проектов. Payload мы выбрали как весьма гибкий и интересный инструмент, предоставляющий большой функционал из коробки, админ-панель и базовую работу с пользователями.
В основном статья будет касаться взаимодействия со стороны backend-части.
Плюсы и преимущества Payload
Упрощает разработку проекта, а это быстрая и простая начальная установка и готовая структура проекта (что в целом может быть и минусом).
Поддержка мультиязычности из коробки.
Предоставляет авторизацию из коробки.
Аутентификация происходит по классической связке «email — password».
Для авторизации используется Bearer-токен.
Сразу весь необходимый набор ручек работы с пользователем:
Также это может быть расширено посредством PassportJs, но на практике у нас не было необходимости его использовать.
Access control на CRUD операции.
Удобен для быстрого прототипирования. Если хочется за 30 минут запустить проект, описать несколько сущностей — решение крайне удобно.
Предоставляет базовый CRUD.
После описания сущности для нее создается набор рутов, готовый для работы:
Query-запросы (GraphQL).
Со стороны frontend появляется возможность выполнять простые запросы, включая сортировки и фильтрацию (equals, less_then, in и т. д.).
Стандартизация запросов. Ошибки, пагинация, ответы и прочее — все находится в едином стиле.
Поддержка Mongodb и Postgres и простая быстрая базовая работа с ними (в нашем случае мы использовали только mongo).
Быстрое описание коллекции и генерация интерфейсов на ее основе:
export const Clients: CollectionConfig = {
slug: 'clients',
auth: {
depth: 1,
tokenExpiration: 28800,
maxLoginAttempts: 5,
lockTime: 30 * 1000,
},
labels: {
plural: 'Клиенты',
singular: 'Клиент',
},
admin: {
useAsTitle: 'name',
},
fields: [
{
name: 'name',
type: 'text',
label: 'Имя',
},
{
name: 'favoriteNumber',
type: 'number',
label: 'Любимое число',
},
{
type: 'date',
label: 'Дата рождения',
name: 'dateOfBirth',
},
],
};
Интерфейс на выходе:
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "clients".
*/
export interface Client {
id: string;
name?: string | null;
favoriteNumber?: number | null;
dateOfBirth?: string | null;
}
Хорошая и удобная админка из коробки:
Система предоставляет множество хуков на сущности и на поля. Часто это может быть очень удобно.
hooks: {
afterRead: [afterReadUser],
afterDelete: [afterDeleteUser],
}
С какими минусами Payload мы столкнулись
Из некоторых плюсов вытекают минусы.
Проблема хуков. Система предоставляет несколько уровней хуков. Одни хуки на уровне полей, вторые — на уровне коллекций. В нашей воле описать хуки на создание, изменение и удаление.
Звучит весьма неплохо. Но на определенном этапе работы с проектом выходит так, что не все вещи удобно и возможно делать через хуки + их становится слишком много.
Это начинает выглядеть как усложнение. Встает проблема с тем, что приходится помнить и следить за всеми описанными хуками. Похоже на проблему с колбэками — это некая непредсказуемость кода: в какой момент и что выполнится? Все слишком нелинейно. Слишком запутанно.
Типы и поля. Больше похоже на то, что они заточены на админ-панель, а не на бэкенд-часть. Яркий пример — это тип boolean, который здесь называется checkbox:
Проблема с mongoose. На момент разработки Payload использовал старый драйвер mongoDb. Обновить его просто так нельзя. Возникают различные проблемы, особенно проблемы, связанные с типами.
Базы данных. Слишком высокий уровень абстракции. БД — mongoose — обертка на Payload. Появляется некая непредсказуемость того, что может произойти.
Концепция Payload заставляет писать БД в стиле ближе к реляционному с огромным количеством таблиц и связей между ними.
Если нужны более сложные запросы, то они будут работать в обход хуков. Приходится очень внимательно следить за этим. Часто это сильно усложняет и замедляет процесс разработки.
Мелкие проблемы, которые возникают в процессе работы:
невозможно типизировать JSON-тип;
нельзя указать минимальное значение массива 0;
и многие другие моменты, которые не являются критичными, но весьма раздражают в процессе работы.
Если нужно сделать более сложную валидацию и проверку данных, то приходится делать кастомный контроллер либо оборачивать дополнительными хуками. Но тогда как будто ломается концепция чего-то «быстрого из коробки».
Приходится использовать самописные вещи для валидации или проводить проверку полей в самом handler.
Из-за специфичной архитектуры невозможно говорить о микросервисах.
В версии до 2.0 graphQl был старый и deprecated, и ты ничего не мог с этим поделать.
Невозможно переписать handler для ошибок.
Форум (community help) в целом заточен на вопросы frontend-части и для backend достаточно бесполезен.
Выводы
При работе с Payload следует учитывать, что могут возникнуть некоторые проблемы, когда мы хотим функционал чуть больший, чем представляется из коробки. Ограничения версий, самописный код может начать конфликтовать с тем, что есть в системе или могут возникнуть другие ситуации, описанные в статье. Но все эти минусы присущи не только Payload, а любым «коробочным решениям».
Если резюмировать весь опыт взаимодействия с Payload, то нужно отметить, что это действительно весьма удобный инструмент для создания прототипов и MVP. В нашем случае он позволил создать два крупных качественных MVP с большим количеством функционала за сжатые сроки.