Уроки, полученные при развертывании SaaS на Next.js и создании CLI-инструмента для сборки проектов
Объясняются основополагающие решения — выбор стека технологий, механизмы аутентификации, поддержка нескольких арендаторов, система оплаты и управление состоянием — а также создание CLI-инструмента, упрощающего настройку проектов Next.js.
Разработка настоящего SaaS-продукта с использованием React и Next.js — это не столько выбор модной библиотеки, сколько правильное принятие десятков незаметных решений ещё до того, как вы вообще начнёте работать с панелью управления. Та же дисциплина, которая позволяет архитектуре продукта выдерживать нагрузку реальных клиентов, проявляется даже в такой обыденной задаче, как создание нового проекта на Next.js — именно поэтому встроенный инструмент командной строки для генерации шаблонов учит того же, что и само создание SaaS: именно скучная настройка определяет успех или неудачу проекта.
Выбор технологий, которые не замедлят вас
После выпуска более одного SaaS-продукта технологический стек обычно принимает предсказуемую форму:
- Next.js в качестве единственной фреймворковой среды для маршрутизации, серверной отрисовки и API-маршрутов, что позволяет избежать необходимости использования разных инструментов для каждой задачи.
Ни один из этих выборов сделан не ради новизны. Вместе они позволяют небольшой команде работать быстро, не накапливая при этом технический долг, который невозможно будет погасить.
Сначала создайте простые основы
У основателей бывает соблазн сразу приступить к созданию панелей управления. Сопротивляйтесь этому желанию. Прежде чем создавать что-либо, предназначенное для пользователей, сначала наладите следующие три аспекта:
- Аутентификация — реализуется с использованием настоящих сессий, а не просто токенов, сохраняемых в localStorage.
- Многоклиентская архитектура — даже если сейчас у вас только один клиент, проектируйте решение с возможностью обслуживания нескольких клиентов с самого начала.
- Хуки для выставления счетов — заранее настроение webhook-ов Stripe позволяет избежать сложной переработки после запуска продукта.
Вот шаблон, который стоит использовать для выполнения API-запросов в рамках конкретного клиента без необходимости повторять код:
// hooks/useTenantFetch.ts
import { useCallback } from "react";
import { useSession } from "next-auth/react";
export function useTenantFetch() {
const { data: session } = useSession();
const fetchScoped = useCallback(
async (endpoint: string, options: RequestInit = {}) => {
if (!session?.tenantId) throw new Error("No active tenant");
const res = await fetch(`/api/${session.tenantId}${endpoint}`, {
...options,
headers: {
...options.headers,
"Content-Type": "application/json",
},
});
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
return res.json();
},
[session]
);
return { fetchScoped };
}
Это небольшой утилитный инструмент, но он спасает от необходимости распространять проверки идентификаторов клиентов по десяткам компонентов позже.
Понимание того, что должно находиться в глобальном состоянии
Не каждый фрагмент данных заслуживает места в Redux. Один из инженеров, работающий в стартапе, поддерживаемом Y Combinator, хорошо это сформулировал: глобальное состояние — это долг, который со временем начинает приносить проценты. Используйте Redux (или любой другой выбранный вами глобальный хранилище) исключительно для тех элементов, которые действительно касаются всего интерфейса — модалок, флагов функций, предпочтений пользователей — а остальное, что на самом деле является просто серверными данными в оболочке интерфейса, пусть обрабатывает React Query или SWR.
Несколько ключевых выводов кратко описывают аспекты создания SaaS-приложений:
- Сначала наладите аутентификацию и систему оплаты, прежде чем вкладывать средства в отлаженный интерфейс.
- Типизация на TypeScript перестаёт быть необязательной, как только начинаются финансовые вложения.
- Избегайте чрезмерной централизации состояния; большинство функций должны находиться в инструментах управления серверным состоянием, а не в глобальном хранилище.
Всё это не связано с стремлением использовать самую новую библиотеку. Оно основано на фундаментальных принципах: заранее урегулируйте вопросы аутентификации, работы с тенантами и финансового учёта, и всё остальное — рост проекта, добавление новых функций, масштабирование — станет гораздо проще реализовывать на этой основе.
Когда сама настройка становится узким местом
Именно желание избавиться от повторяющейся и подверженной ошибкам работы по настройке в конечном итоге приводит к автоматизации самих стандартных шагов. Каждый фронтенд-разработчик знает эту рутину: сначала создаётся структура нового проекта с помощью create-next-app, а затем начинается сама утомительная работа. Необходимо создать папку components, разделить содержимое ui и features, настроить hooks, связать общие types, написать вспомогательные функции, настроить псевдонимы путей и организовать иерархию папок — и может пройти целый час, прежде чем будет написана хотя бы одна строка настоящей бизнес-логики.
После многократного выполнения этого ритуала естественным следующим шагом стало его автоматизирование, в результате чего появился первый опубликованный пакет с открытым исходным кодом для npm: nexarch-cli.
Основная проблема
Стандартные шаблоны старта Next.js предоставляют пустую основу, а не архитектуру, готовую к использованию в производстве. Современные приложения обычно требуют:
- Четкого разделения логики отображения и бизнес-логики
- Модульной структуры, основанной на функциях
- Масштабируемых определений типов и утилитных оберток
- Единообразных правил, которым может следовать вся команда
Повторное создание всего этого вручную для каждого прототипа или проекта клиента занимает много времени, сопровождается неоднородностью и подвержено ошибкам.
Что на самом деле делает nexarch-cli
nexarch-cli — это интерактивный инструмент командной строки, предназначенный для быстрого создания чистой, модульной архитектуры Next.js в течение нескольких секунд. Вместо ручного создания вложенных папок и файлов-заглушек достаточно ответить на несколько вопросов в терминале, и инструмент сам настроит базовую структуру.
Основные его функции включают:
- Интерактивное создание структуры с помощью простых вопросов в терминале, адаптированных под ваши потребности.
- Модульная архитектура с заранее настроенными конвенциями, позволяющими масштабироваться по мере роста приложения.
- Отсутствие необходимости в глобальной установке — инструмент запускается по требованию с помощью
npx. - Соответствие современным конвенциям Next.js и React, что обеспечивает согласованность структуры каталогов с современными практиками.
Запуск инструмента
Нет необходимости устанавливать что-либо глобально. Вы можете запустить его напрямую:
npx nexarch-cli
После ответов на вопросы структура вашего проекта будет сгенерирована и готова к фактической разработке.
Создание и публикация этого инструмента в качестве первого инструмента для разработчиков сопровождались сложным процессом обучения. Несколько важных уроков:
- Интерфейс терминала так же важен, как и сам код. Корректная обработка завершения процессов, четкое отображение запросов и ясные сообщения об ошибках имеют такое же значение, как и логика генерации файлов.
- Операции с файловой системой скрывают множество неочевидных случаев. Написание рекурсивных функций для создания каталогов и шаблонов файлов, которые будут корректно работать на разных операционных системах, требует тщательного и многократного тестирования.
package.json (bin), работа с правами доступа к файлам с помощью chmod и поддержание минимального уровня нагрузки от зависимостей позволяют понять, как на самом деле работают инструменты командной строки на основе Node.Текущее состояние проекта
Этот инструмент по-прежнему находится на ранней стадии развития как проект с открытым исходным кодом, и ему полезен внешний вклад на этапе формирования. Код хранится по адресу github.com/CaffeineLogs/nexarch-cli, а опубликованный пакет можно найти в реестре npm под именем nexarch-cli.
Все, у кого другой предпочтительный формат проекта или кто сталкивается с ситуациями, которые пока плохо обрабатываются в существующих инструментах, могут задокументировать их как проблему в репозитории. Предложения относительно возможных дальнейших шагов — такие как готовые настройки стилизации или предустановленные решения для управления состоянием — также приветствуются в качестве тем для обсуждения или комментариев.
Независимо от того, решаете ли вы, что должно входить в Redux, или как следует организовать новый проект на Next.js, один урок остается неизменным: те части проекта, которые кажутся наиболее сложными — аутентификация, управление тенантами, оплата, структура папок — именно те элементы, которые важно правильно настроить, а часто и автоматизировать, прежде чем переходить к чему-либо ещё.