Как я поэтапно выношу фронтенд в отдельное SPA на Vue/React из Laravel-проекта
Иногда Laravel-проект начинает задыхаться от Blade-шаблонов и jQuery. Хочется нормальный фронт на Vue/React, но переписать всё разом страшно: бизнес живёт на текущем коде. Я стараюсь делать постепенную миграцию в сторону SPA, не ломая прод.
Расскажу, как я это делаю по шагам.
1. Определяю «островок» для первой миграции
Я никогда не начинаю с переписывания всего сайта.
Сначала выбираю один кусок, который:
- достаточно изолирован функционально (личный кабинет, раздел заказов, админ-страница);
- даёт ощутимую пользу фронту (динамика, таблицы, фильтры);
- можно отдать на отдельный роут без переделки всей навигации.
Задача: получить один живой блок на Vue/React, который уже работает через API.
2. Навожу порядок в API на Laravel
Перед фронтом я привожу эндпоинты к более-менее нормальному виду:
- чёткие URL через api.php, например /api/v1/profile, /api/v1/orders;
- FormRequest для валидации;
- Resources для ответов, чтобы фронт не зависел от структуры моделей;
- единый формат ошибок.
Пока фронтенд пилится, API уже можно тестировать через Postman/Insomnia.
3. Решаю, как жить с авторизацией
Вариантов обычно два:
1. SPA и Laravel на одном домене
- использую Sanctum;
- логин → cookie, дальше запросы с withCredentials.
2. Разные домены (отдельный фронтовый хост)
- чаще использую токены (тот же Sanctum, но через токен);
- фронт хранит токен в памяти/secure storage и шлёт в заголовке.
Главное договориться: как обрабатываем 401/403 и что делает фронт при истечении сессии.
4. Встраиваю SPA в существующий проект Типовой сценарий:
- Laravel продолжает отдавать основную оболочку (header/footer, layout);
- для конкретного пути, например /app, Blade отдаёт один «корневой» div и подключённый бандл Vue/React;
- роутинг внутри /app уже делает фронтенд.
Так я могу оставить старые страницы как есть и постепенно переносить их внутрь SPA.
Пример Blade:
@extends('layouts.app')
@section('content')
@endsection
А дальше Vite/Webpack монтирует приложение в #spa-root.
5. Структура фронта: сразу думаю на вырост Стараюсь с первого дня разложить проект:
- src/app – точка входа, роутер, провайдеры;
- src/pages – страницы;
- src/features – фичи (логин, профиль, фильтры);
- src/entities – сущности (User, Order);
- src/shared – общие компоненты и утилиты.
Это позволяет:
- постепенно добавлять новые разделы;
- параллельно жить со старым Blade, не превращаясь в кашу.
6. Ш**люз между старым и новым
На** переходном периоде часто нужно, чтобы:
- часть страниц рендерилась старым Blade;
- часть – из SPA.
Я делаю так:
- для ссылок на новый раздел использую обычные [;
- внутри SPA уже живёт свой роутер;
- если нужно, оставляю fallback: при ошибке фронта всегда можно временно вернуть старую страницу.
Важно не мешать два роутера на одном и том же URL без необходимости.
7. **Чек-лист по постепенной миграции
*** Определён первый изолированный раздел для миграции. * Для него есть понятный набор API-эндпоинтов на Laravel. * Авторизация и обработка ошибок продуманы заранее. * SPA монтируется в отдельный маршрут, не ломая остальной сайт. * Структура фронта изначально разбита на слои (app/pages/features/entities/shared). * Есть план, какие разделы переносить дальше и в каком порядке.
Итог Вынос фронта из Laravel-монолита в отдельное SPA не обязан быть большим взрывом. Если начать с одного раздела, сразу навести порядок в API и аккуратно встроить Vue/React через отдельный маршрут, проект можно спокойно перетащить в современный стек без жёстких переездов и вечного «сделаем новый фронт, когда будет время».