Переход с Next.js Pages Router на App Router — это не просто смена файловой структуры, это смена парадигмы выполнения кода. Pages Router опирался на изоляцию данных на уровне страницы (getServerSideProps, getStaticProps) и выполнение всего дерева компонентов на клиенте. App Router вводит React Server Components (RSC) по умолчанию, глубокую вложенность лейаутов (Nested Layouts) и изоляцию состояний загрузки через потоковую передачу (Suspense).
Для крупных легаси-проектов ручная миграция сопряжена с огромным риском регрессии. Использование AI-агентов (в связке с инструментами AST-анализа и файловой системы) позволяет автоматизировать процесс: агент анализирует зависимости старой страницы, декомпозирует её на серверную часть (выборка данных) и клиентскую часть (интерактивность с 'use client'), и генерирует page.tsx, layout.tsx и loading.tsx в директории app/.
Процесс миграции требует инверсии потока данных. Данные больше не прокидываются сверху вниз от getServerSideProps ко всем дочерним компонентам; компоненты сами запрашивают нужные им данные на сервере.
[Pages Router: pages/dashboard.tsx]
+------------------------------------+
| export const getServerSideProps | ---> УДАЛЯЕТСЯ
| function Dashboard({ user, data }) | ---> ДЕКОМПОЗИРУЕТСЯ
| - onClick={handleClick} | ---> ВЫНОСИТСЯ В 'use client'
+------------------------------------+
|
[AI Migration Pipeline]
|
v
[App Router: app/dashboard/]
├── page.tsx (Server Component: async fetch(data), рендер скелета)
├── layout.tsx (Server Component: fetch(user), обертка UI)
└── ClientChart.tsx('use client': интерактивность, onClick)Агент парсит AST старой страницы, находя хуки состояния (useState) и обработчики событий.
Интерактивные элементы выносятся в новые файлы с директивой 'use client'.
Логика из getServerSideProps превращается в нативные async/await вызовы внутри серверной page.tsx.
Импорты (next/router, next/head) заменяются на новые эквиваленты App Router.
Какая стратегия декомпозиции страницы из Pages Router в App Router является архитектурно корректной для сохранения преимуществ RSC?
getServerSideProps на нативные fetch внутри RSC.pages/api/* на прямые вызовы мутаций (Server Actions) из клиентских или серверных компонентов в директории app/.Пример промпта и архитектуры для AI-агента, который берет старый файл из pages/ и генерирует новый page.tsx для app/.
import fs from 'fs/promises';
import path from 'path';
import { generateWithAI } from '@/lib/ai-agent';
// Функция, имитирующая работу AI-пайплайна по миграции файла
export async function migratePageToAppRouter(pagesFilePath: string) {
const sourceCode = await fs.readFile(pagesFilePath, 'utf-8');
// Системный промпт для AI-агента
const prompt = `
Ты Staff AI Инженер. Твоя задача — мигрировать файл Next.js Pages Router в App Router.
Соблюдай строгие правила:
1. Удали getServerSideProps/getStaticProps. Замени их на прямые async вызовы данных внутри серверного компонента.
2. По умолчанию делай компонент Server Component.
3. Если в коде есть useState, useEffect, onClick — выдели эту часть в отдельный клиентский компонент с директивой 'use client' и импортируй его в серверный page.tsx.
4. Замени импорты 'next/router' на 'next/navigation'.
5. Замени импорты 'next/head' на экспорт константы/функции \`metadata\`.
Исходный код:
${sourceCode}
Верни JSON с двумя полями:
- serverCode: код для app/[route]/page.tsx
- clientCode: код для выделенных клиентских компонентов (если нужны, иначе null)
`;
// Запуск LLM
const result = await generateWithAI(prompt);
// Парсинг результата и запись в новую файловую структуру
const routeName = path.basename(pagesFilePath, '.tsx');
const appDirPath = path.join(process.cwd(), 'app', routeName);
await fs.mkdir(appDirPath, { recursive: true });
await fs.writeFile(path.join(appDirPath, 'page.tsx'), result.serverCode);
if (result.clientCode) {
await fs.writeFile(path.join(appDirPath, 'ClientWrapper.tsx'), result.clientCode);
}
return { success: true, newPath: appDirPath };
}Какая производственная опасность возникает, если AI-ассистент некорректно переместит серверную логику с приватными ключами в компонент с директивой 'use client'?
Самая частая ошибка AI-агента — просто добавить 'use client' в начало старого файла pages/xxx.tsx и положить его в app/. Это "решает" проблему миграции, но полностью уничтожает все преимущества App Router, делая весь маршрут клиентским и отправляя весь код в бандл.
Если агент некорректно разделит код и оставит обращение к переменным окружения (без префикса NEXT_PUBLIC_) внутри компонента с 'use client', это приведет к ошибкам в рантайме или, что хуже, утечке конфигурации.
В Pages Router хук useRouter предоставлял доступ к query, pathname, push и событиям. В App Router они разделены (useRouter, usePathname, useSearchParams из next/navigation). Агент может по ошибке пытаться использовать router.query в новом API.