Перевёл интернет-магазин с Nuxt на Next.js
Опыт миграции крупного интернет-магазина с Nuxt на Next.js: почему приняли решение, какие проблемы встретили и какие метрики улучшили после релиза в 2025 году.
Статья была полезной?
Опыт миграции крупного интернет-магазина с Nuxt на Next.js: почему приняли решение, какие проблемы встретили и какие метрики улучшили после релиза в 2025 году.
Статья была полезной?
Миграция заняла три месяца активной разработки и один месяц тестирования на проде с частичным переключением трафика. Результат — заметное ускорение страниц, сокращение времени сборки и положительная динамика конверсии в первые 12 недель после релиза.
Проект — мультинаправленный интернет-магазин с 120 000 уников в месяц и каталожной структурой из 62 000 SKU. На момент принятия решения (март 2025) кодовая база была на Nuxt 3 с Nitro как серверной платформой. Несмотря на то, что Nuxt оставался стабильным, у нашей команды возникла совокупность причин для миграции:
Учитывая эти факторы, решение приняли 15 марта 2025 года. Временные рамки были критичны: к майским распродажам нужно было иметь стабильную платформу для увеличенного трафика, поэтому план миграции закладывался на 12 недель разработки с поэтапным переключением трафика.
Перенос с Vue/Nuxt на React/Next.js — это не только замена синтаксиса компонентов. Сложности охватывали архитектурные, инфраструктурные и SEO-аспекты.
Nuxt предоставляет явные хуки типа asyncData и встроенную поддержку middleware, автоматически обрабатывает маршруты по файловой структуре и легче интегрируется с плагинами Nuxt. В Next.js ситуация изменилась с выпуском App Router, но миграция требовала решения о том, использовать ли Pages Router или App Router и как совмещать их с концепциями ISR, SSG и SSR.
Конкретная проблема: у нас было много вложенных динамических роутов вроде /category/[categorySlug]/[filter]/page/[page]. В Nuxt они работали «из коробки», а в Next.js пришлось вручную продумать стратегию генерации и fallback-ов, особенно для SSG-каталогов.
В проекте использовался Vuex с модульными state/actions для корзины, авторизации и управления фильтрами. Переписывание на Redux Toolkit заняло время; мы в итоге выбрали сочетание Redux Toolkit + RTK Query для API-кеша, а для локального UI-состояния — Zustand. Перенос около 1200 строк мутаций и действий в эквивалентные селекторы и слайсы занял примерно 3 недели для двух разработчиков.
Scoped стили, слоты, динамические директивы Vue (v-if, v-for, v-bind) требовали ручной трансляции в JSX/TSX. Кроме того, множество UI-компонентов использовали специфические возможности Vue Transition, которые пришлось заменять на React-ориентированные библиотеки или простые CSS-анимации.
Некоторые модульные решения Nuxt (nuxt-image, nuxt-i18n, nuxt-auth) не имели прямых аналогов, поэтому часть функционала приходилось реализовывать с нуля или адаптировать сторонние библиотеки (next/image, next-i18next, next-auth). Это повлекло дополнительное тестирование и полировку.
Самый большой страх — потерять органический трафик. Первые две недели после частичного переключения мы наблюдали падение индексации и некоторых директив в Search Console: покрытие страниц уменьшилось на 1.2%, а органический трафик упал на 9% в первой неделе после переключения. Это потребовало срочной валидации редиректов, генерации sitemap и проверки canonical-меток.
Мы разработали поэтапный план, который позволил минимизировать риски и раскатать проект инкрементально.
Составили список критичных страниц, сервисов и интеграций. Отметили 180 ключевых URL (категории, карточки товара, страницы брендов, аккаунты) и приоритизировали их по трафику и конверсии.
Сделали малый прототип на Next.js для карточки товара и корзины на поддомене shop-next.example.com, чтобы проверить время ответа, интеграцию с картинками и checkout flow.
Приняли решение размещать Next.js на Vercel (edge + serverless functions) с fallback на AWS Lambda для некоторых legacy endpoints. CI через GitHub Actions с кэшированием node_modules и .next/cache.
Переписали маршрутизацию: все критичные маршруты сделали SSR или SSG с On-demand revalidation для страниц каталога. Выполнили маппинг URL 1:1, чтобы избежать лишних редиректов.
Компоненты перевели на TSX по приоритетам — сначала карточки товара, затем каталог, затем checkout и user flows.
Подключили платежные шлюзы, аналитические хуки, next/image оптимизацию и edge middleware для геолокации и A/B.
Запустили A/B тесты на 5% трафика, мониторили метрики: TTFB, LCP, CLS, CR. Исправляли ошибки и корректировали редиректы.
Раскатили 50% трафика, затем 100% после стабилизации. Финальный релиз состоялся 12 июня 2025 года.
Фрагмент next.config.js, который использовали для редиректов и image optimization:
module.exports = {
reactStrictMode: true,
images: {
domains: ['cdn.example.com', 'images.example.com'],
deviceSizes: [320, 480, 768, 1024, 1600],
},
async redirects() {
return [
{ source: '/old-product/:slug', destination: '/product/:slug', permanent: true },
{ source: '/promo/2024/:path*', destination: '/promo/archived/:path*', permanent: false },
]
}
}Пример простого сервера (middleware) для гео-персонализации цен в Next.js edge middleware:
import { NextResponse } from 'next/server'
export function middleware(request) {
const country = request.geo?.country || 'US'
const res = NextResponse.next()
res.cookies.set('X-USER-COUNTRY', country)
return res
}
export const config = { matcher: ['/product/:path*', '/category/:path*'] }Небольшой пример рефакторинга Vue composable в React hook для корзины:
// Vue (пример)
export function useCart() {
const state = reactive({ items: [] })
function add(item) { state.items.push(item) }
return { state, add }
}
// React Hook (эквивалент)
import { useState, useCallback } from 'react'
export function useCart() {
const [items, setItems] = useState([])
const add = useCallback((item) => setItems(prev => [...prev, item]), [])
return { items, add }
}Сохранение SEO-позиций было критичным требованием. Мы выстроили четкую стратегию по сохранению URL-структуры, валидации метаданных и минимизации индексационного дельта-времени.
Первое правило — никаких изменений канонических URL без острой необходимости. Мы провели автоматическую генерацию файла редиректов из текущей sitemap и маршрутов Nuxt, затем проверили её вручную для 180 приоритетных страниц.
// Пример записи редиректа в vercel.json (альтернатива next.config.js)
{
"redirects": [
{ "source": "/old-category/:slug", "destination": "/category/:slug", "permanent": true }
]
}Для устаревших акций и промо-страниц использовали 410 ответ для краткого удаления (чтобы поисковики быстро исключили такие страницы), а для страниц со сменой структуры — 301 или 308 в зависимости от сохранения query-параметров.
Мы экспортировали все мета-теги и схемы из Nuxt-приложения и подключили их в Head компонентов Next.js. Особое внимание уделили:
Пример вставки schema.org на сервере (Server Component / getServerSideProps):
export async function getServerSideProps(context) {
const product = await fetchProduct(context.params.slug)
return {
props: {
product,
schema: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Product',
'name': product.title,
'sku': product.sku,
})
}
}
}Для отслеживания состояния индексации использовали Google Search Console, Screaming Frog и внутренние лог-файлы обращений поисковых ботов. В течение первой недели после переключения мы держали функционал отката готовым: трафик можно было быстро переключить обратно на Nuxt через DNS и reverse-proxy в течение 30 минут при критических ошибках.
Результат в цифрах (май–август 2025):
По итогам 12-недельного наблюдения после полного релиза 12 июня 2025 года получили следующую статистику по ключевым метрикам:
Самое ценное — не технология как таковая, а возможность итеративно улучшать опыт пользователя, быстрее выпускать изменения и при этом не потерять трафик.
Ключевые выводы и рекомендации для тех, кто рассматривает миграцию "миграция nuxt на next.js":
Мы потратили на миграцию около 1200 человеко-часов (5 разработчиков, 1 инженер по съёму метрик, 1 DevOps-инженер, 1 QA) в период с 15 марта по 12 июня 2025. Это инвестиция оказалась оправданной: ускорение страниц дало не только технические преимущества, но и улучшение бизнес-показателей.
Если резюмировать простыми словами: миграция nuxt на next.js при корректном планировании и поэтапной выкладке даёт реальную выгоду в скорости и в удобстве развития продукта, но потребует внимания к SEO, состоянию и интеграциям. Важно держать в фокусе процесс переключения трафика, готовность к откату и мониторинг ключевых метрик в первые недели после релиза.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…