← Все статьи

Lovable: 400 маршрутов с Next.js на TanStack Start без одномоментного переключения

Параллельный прокси, #shared, адаптеры и агенты: lovable.dev ушёл с Vercel на свой стек при 42 млн посетителей в месяц.

Lovable: 400 маршрутов с Next.js на TanStack Start без одномоментного переключения
Содержание

Коротко

Команда Lovable перенесла lovable.dev (~400 маршрутов, 850K+ строк, 42M+ уникальных посетителей в месяц) с Next.js на Vercel на TanStack Start на собственной платформе. Ключ — не «переписать и переключить», а месяцы параллельной работы двух фреймворков за прокси, общая папка кода и постепенный выкат группами маршрутов.

Что произошло

Сайт раньше жил на Next.js; Vercel закрывал проблемы масштаба, но продукт сам хостит приложения пользователей как воркеры Cloudflare workerd. Цель миграции — есть свою же кашу: тот же путь обслуживания, что у миллионов чужих приложений, короткий цикл обратной связи и единый стек для агента-сборщика.

Миграция шла полгода, пока кодовая база росла с ~350K до 850K+ строк. Перед обоими стеками стоял прокси: по маршруту и флагу выбирал Next.js или TanStack Start. Жёсткая навигация между фреймворками дороже мягкой (5 с против ~1,5 с медиана), поэтому маршруты сгруппировали по типичным пользовательским путям и катили группы целиком. Для сглаживания вспышки белого экрана включили плавные переходы между документами (@view-transition).

Общий код вынесли под псевдоним #shared/ с линтом «не импортировать next и TanStack». Разницу API закрыли адаптерами через псевдонимы TypeScript (@platform/router и т.п.). К концу доля Next.js-специфичного кода упала примерно до 3%. Много механической перекладки сделали агенты по повторяемым навыкам; ревью и выкат вёл один инженер.

На панели управления при 20% трафика случился инцидент нехватки памяти на изолятах V8: лишние мегабайты статики в бандле убили переиспользование изолятов. Откат за минуты, потом отложенная загрузка тяжёлых кусков.

Почему это важно

Это редкий публичный разбор миграции фронта на десятки миллионов пользователей без одномоментного переключения. Главный архитектурный тезис: фреймворк — тонкая оболочка, 90–95% кода — переносимое ядро. Тогда смена стека становится проектом адаптеров и выката, а не переписыванием продукта.

Второй урок — операционный: детерминированные флаги для тестов, один внешний процентный выкат за раз, синтетика плюс реальные метрики загрузки у пользователей, быстрый откат важнее идеального предсказания.

На практике

  1. Перед сменой фреймворка вынесите next/image, шрифты, вход пользователя и переводы на переносимые библиотеки — сузьте поверхность миграции.
  2. Держите два стека за одним прокси и катите группами маршрутов, а не по одной странице из середины пользовательского сценария.
  3. Введите #shared + запрет импортов фреймворка в линтере; новые возможности по умолчанию пишите туда.
  4. Различия API закрывайте адаптерами через псевдонимы модулей, а не контекстом на каждый клик.
  5. Следите за размером бандла изолята и резидентной памятью: «ещё пара мегабайт JSON» может сорвать переиспользование воркеров на краю сети.

Итог

Lovable показал, как агенты + жёсткие правила переносимости позволяют одному разработчику сменить веб-фреймворк под растущей кодовой базой. Сайт теперь — ещё один бандл среди десятков миллионов приложений на той же платформе.