# Checklist Migration Next.js 15 & React 19 > **Phiên bản:** Next.js 15.x | React 19.x > **Cập nhật:** 2025 > **Mức độ:** Production-ready migration guide --- ## Mục lục - [1. Pre-Migration Checks](#1-pre-migration-checks) - [2. Breaking Changes](#2-breaking-changes) - [3. App Router Specific Changes](#3-app-router-specific-changes) - [4. Third-party Libraries](#4-third-party-libraries) - [5. Testing Checklist](#5-testing-checklist) --- ## 1. Pre-Migration Checks ### 1.1 Môi trường & Node.js - [ ] **Kiểm tra Node.js version** — Next.js 15 yêu cầu tối thiểu **Node.js 18.17.0** ```bash node --version # Yêu cầu: >= 18.17.0 ``` - [ ] Upgrade Node.js nếu cần (khuyến nghị dùng **Node.js 20 LTS** hoặc **22 LTS**) - [ ] Kiểm tra `.nvmrc` hoặc `.node-version` trong project và cập nhật - [ ] Cập nhật CI/CD pipeline (GitHub Actions, GitLab CI, Vercel...) với Node.js version mới - [ ] Kiểm tra `engines` field trong `package.json` ```json { "engines": { "node": ">=18.17.0" } } ``` ### 1.2 Backup & Chuẩn bị - [ ] Tạo branch mới cho migration (ví dụ: `feat/nextjs-15-migration`) - [ ] Commit toàn bộ thay đổi hiện tại, đảm bảo working tree sạch - [ ] Backup `package.json` và `package-lock.json` / `yarn.lock` / `pnpm-lock.yaml` - [ ] Đảm bảo test suite hiện tại đang **PASS 100%** trước khi migrate - [ ] Ghi chép lại các custom configurations hiện có (`next.config.js`, middleware...) ### 1.3 Upgrade Dependencies - [ ] Chạy codemod tự động của Next.js 15 ```bash npx @next/codemod@canary upgrade latest ``` - [ ] Hoặc upgrade thủ công ```bash # npm npm install next@latest react@latest react-dom@latest # yarn yarn add next@latest react@latest react-dom@latest # pnpm pnpm add next@latest react@latest react-dom@latest ``` - [ ] Kiểm tra version sau khi upgrade ```bash npx next --version # Expected: Next.js 15.x.x ``` - [ ] Upgrade TypeScript lên **5.x** (nếu dùng TypeScript) ```bash npm install typescript@latest @types/node@latest @types/react@latest @types/react-dom@latest ``` - [ ] Kiểm tra `eslint-config-next` tương thích ```bash npm install eslint-config-next@latest ``` ### 1.4 Kiểm tra Dependencies Conflicts - [ ] Chạy audit dependencies ```bash npm ls react react-dom # Đảm bảo không có version conflict ``` - [ ] Kiểm tra `peerDependencies` warnings - [ ] Resolve tất cả `ERESOLVE` errors trước khi tiếp tục --- ## 2. Breaking Changes Cần Xử Lý ### 2.1 Async `params` trong Route Segments > **⚠️ BREAKING:** `params` prop trong pages, layouts, metadata giờ là **Promise** — phải `await` trước khi dùng. - [ ] Tìm tất cả files sử dụng `params` trong `app/` directory ```bash grep -r "params\." app/ --include="*.tsx" --include="*.ts" -l ``` - [ ] Cập nhật **Page components** để `await params` ```tsx // ❌ TRƯỚC (Next.js 14) export default function Page({ params }: { params: { slug: string } }) { return

{params.slug}

; } // ✅ SAU (Next.js 15) export default async function Page({ params, }: { params: Promise<{ slug: string }>; }) { const { slug } = await params; return

{slug}

; } ``` - [ ] Cập nhật **Layout components** ```tsx // ❌ TRƯỚC export default function Layout({ children, params, }: { children: React.ReactNode; params: { lang: string }; }) { return {children}; } // ✅ SAU export default async function Layout({ children, params, }: { children: React.ReactNode; params: Promise<{ lang: string }>; }) { const { lang } = await params; return {children}; } ``` - [ ] Cập nhật `generateMetadata` function ```tsx // ❌ TRƯỚC export async function generateMetadata({ params, }: { params: { id: string }; }) { return { title: `Product ${params.id}` }; } // ✅ SAU export async function generateMetadata({ params, }: { params: Promise<{ id: string }>; }) { const { id } = await params; return { title: `Product ${id}` }; } ``` - [ ] Cập nhật `generateStaticParams` - [ ] Chạy codemod tự động cho `params` ```bash npx @next/codemod@canary next-async-request-api . ``` ### 2.2 Async `searchParams` > **⚠️ BREAKING:** `searchParams` trong Page components giờ là **Promise**. - [ ] Tìm tất cả files sử dụng `searchParams` ```bash grep -r "searchParams" app/ --include="*.tsx" --include="*.ts" -l ``` - [ ] Cập nhật Page components có `searchParams` ```tsx // ❌ TRƯỚC export default function SearchPage({ searchParams, }: { searchParams: { q: string; page: string }; }) { return
Query: {searchParams.q}
; } // ✅ SAU export default async function SearchPage({ searchParams, }: { searchParams: Promise<{ q: string; page: string }>; }) { const { q, page } = await searchParams; return
Query: {q}
; } ``` - [ ] Cập nhật `generateMetadata` sử dụng `searchParams` - [ ] Kiểm tra Client Components — nếu cần `searchParams` trong Client Component, dùng `useSearchParams()` hook thay thế ```tsx // ✅ Client Component — dùng hook "use client"; import { useSearchParams } from "next/navigation"; export default function SearchClient() { const searchParams = useSearchParams(); const q = searchParams.get("q"); return
Query: {q}
; } ``` ### 2.3 Async `cookies()` và `headers()` > **⚠️ BREAKING:** Các functions `cookies()`, `headers()`, `draftMode()` từ `next/headers` giờ trả về **Promise**. - [ ] Tìm tất cả usages ```bash grep -r "cookies()\|headers()\|draftMode()" app/ --include="*.tsx" --include="*.ts" -l ``` - [ ] Cập nhật `cookies()` ```tsx // ❌ TRƯỚC import { cookies } from "next/headers"; export default function Page() { const cookieStore = cookies(); const token = cookieStore.get("token"); return
{token?.value}
; } // ✅ SAU import { cookies } from "next/headers"; export default async function Page() { const cookieStore = await cookies(); const token = cookieStore.get("token"); return
{token?.value}
; } ``` - [ ] Cập nhật `headers()` ```tsx // ❌ TRƯỚC import { headers } from "next/headers"; export default function Page() { const headersList = headers(); const userAgent = headersList.get("user-agent"); return
{userAgent}
; } // ✅ SAU import { headers } from "next/headers"; export default async function Page() { const headersList = await headers(); const userAgent = headersList.get("user-agent"); return
{userAgent}
; } ``` - [ ] Cập nhật `cookies()` trong **Server Actions** ```tsx // ✅ SAU — trong Server Action "use server"; import { cookies } from "next/headers"; export async function setTheme(theme: string) { const cookieStore = await cookies(); cookieStore.set("theme", theme); } ``` - [ ] Cập nhật `draftMode()` ```tsx // ✅ SAU import { draftMode } from "next/headers"; export default async function Page() { const { isEnabled } = await draftMode(); return
Draft: {isEnabled ? "ON" : "OFF"}
; } ``` - [ ] Chạy codemod cho headers/cookies ```bash npx @next/codemod@canary next-async-request-api . ``` ### 2.4 `forwardRef` Deprecated — React 19 > **⚠️ BREAKING (React 19):** `ref` giờ là prop thông thường. `forwardRef` không còn cần thiết và sẽ bị deprecated. - [ ] Tìm tất cả `forwardRef` usages ```bash grep -r "forwardRef" src/ components/ --include="*.tsx" --include="*.ts" -l ``` - [ ] Refactor components dùng `forwardRef` ```tsx // ❌ TRƯỚC (React 18) import { forwardRef } from "react"; const Input = forwardRef( ({ placeholder }, ref) => { return ; } ); Input.displayName = "Input"; export default Input; // ✅ SAU (React 19) — ref là prop bình thường type InputProps = { placeholder: string; ref?: React.Ref; }; export default function Input({ placeholder, ref }: InputProps) { return ; } ``` - [ ] Cập nhật TypeScript types cho `ref` prop ```tsx // ✅ Pattern chuẩn React 19 với TypeScript type ButtonProps = React.ComponentProps<"button"> & { variant?: "primary" | "secondary"; }; export default function Button({ variant = "primary", ref, ...props }: ButtonProps) { return {state?.error &&

{state.error}

} ); } ``` ### 3.3 Metadata API - [ ] Kiểm tra `generateMetadata` async pattern (xem phần 2.1) - [ ] Kiểm tra `viewport` export — đã tách khỏi `metadata` object ```tsx // ❌ TRƯỚC — viewport trong metadata export const metadata = { themeColor: "#000000", viewport: "width=device-width, initial-scale=1", }; // ✅ SAU — viewport export riêng import type { Viewport } from "next"; export const viewport: Viewport = { themeColor: "#000000", width: "device-width", initialScale: 1, }; export const metadata = { title: "My App", }; ``` - [ ] Kiểm tra `metadataBase` được set trong root layout ### 3.4 Route Handlers - [ ] Kiểm tra Route Handlers (`app/api/**/route.ts`) vẫn hoạt động - [ ] Cập nhật `params` trong Route Handlers ```tsx // ❌ TRƯỚC export async function GET( request: Request, { params }: { params: { id: string } } ) { return Response.json({ id: params.id }); } // ✅ SAU export async function GET( request: Request, { params }: { params: Promise<{ id: string }> } ) { const { id } = await params; return Response.json({ id }); } ``` - [ ] Kiểm tra `NextRequest` / `NextResponse` vẫn import đúng ### 3.5 Middleware Updates - [ ] Kiểm tra `middleware.ts` vẫn hoạt động đúng - [ ] Kiểm tra `matcher` config trong middleware ```tsx // middleware.ts export const config = { matcher: [ "/((?!_next/static|_next/image|favicon.ico).*)", ], }; ``` - [ ] Test authentication middleware flow - [ ] Kiểm tra middleware không sử dụng Node.js-specific APIs (chạy trên Edge Runtime) ### 3.6 Error Handling - [ ] Kiểm tra `error.tsx` trong các route segments - [ ] Kiểm tra `global-error.tsx` trong root app directory - [ ] Đảm bảo `error.tsx` là Client Component ```tsx // app/error.tsx "use client"; // ← BẮT BUỘC export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { return (

Đã có lỗi xảy ra!

); } ``` ### 3.7 Loading UI & Suspense - [ ] Review `loading.tsx` files - [ ] Kiểm tra Suspense boundaries vẫn hoạt động đúng - [ ] Test streaming SSR behavior - [ ] Kiểm tra `loading.tsx` không bị conflict với Suspense manual ### 3.8 Image Component - [ ] Kiểm tra `next/image` usage — API ổn định, không có breaking change lớn - [ ] Đảm bảo `alt` prop có giá trị meaningful (accessibility) - [ ] Kiểm tra `remotePatterns` trong `next.config.js` thay vì `domains` (deprecated) ```js // next.config.js module.exports = { images: { // ❌ DEPRECATED // domains: ['example.com'], // ✅ ĐÚNG remotePatterns: [ { protocol: "https", hostname: "example.com", port: "", pathname: "/images/**", }, ], }, }; ``` --- ## 4. Third-party Libraries — Kiểm Tra Tương Thích ### 4.1 State Management - [ ] **Redux Toolkit** — Kiểm tra version `>= 2.x` tương thích React 19 ```bash npm ls @reduxjs/toolkit react-redux # react-redux >= 9.x cho React 19 ``` - [ ] **Zustand** — Kiểm tra version `>= 4.x` ```bash npm ls zustand # zustand >= 4.4.x cho React 19 ``` - [ ] **Jotai** — Kiểm tra version `>= 2.x` - [ ] **Recoil** — ⚠️ Chú ý: Recoil không được maintain tích cực, cân nhắc migrate sang Jotai ### 4.2 Data Fetching & Server State - [ ] **TanStack Query (React Query)** — Yêu cầu `>= 5.x` cho React 19 ```bash npm ls @tanstack/react-query # Yêu cầu: >= 5.0.0 ``` - [ ] **SWR** — Kiểm tra version `>= 2.x` ```bash npm ls swr # swr >= 2.2.x khuyến nghị ``` - [ ] **Apollo Client** — Kiểm tra `>= 3.9.x` cho React 19 support - [ ] **tRPC** — Kiểm tra version `>= 11.x` ### 4.3 UI Component Libraries - [ ] **shadcn/ui** — Cập nhật components, tương thích tốt với React 19 ```bash npx shadcn@latest diff # Xem thay đổi ``` - [ ] **Radix UI** — Kiểm tra `>= 1.x` primitives ```bash npm ls @radix-ui/react-dialog # Kiểm tra từng package ``` - [ ] **Headless UI** — Kiểm tra version `>= 2.x` cho React 19 - [ ] **Chakra UI** — Kiểm tra `>= 3.x` (có breaking changes lớn) - [ ] **Material UI (MUI)** — Kiểm tra `>= 6.x` cho React 19 ```bash npm ls @mui/material # MUI >= 6.0.0 hỗ trợ React 19 ``` - [ ] **Ant Design** — Kiểm tra `>= 5.x` - [ ] **Mantine** — Kiểm tra `>= 7.x` ### 4.4 Form Libraries - [ ] **React Hook Form** — Kiểm tra version `>= 7.x` ```bash npm ls react-hook-form # >= 7.50.x cho React 19 ``` - [ ] **Formik** — ⚠️ Chú ý: Formik không được maintain tích cực - [ ] **Zod** (validation) — Kiểm tra `>= 3.x`, tương thích tốt ### 4.5 Animation - [ ] **Framer Motion** — Kiểm tra `>= 11.x` cho React 19 ```bash npm ls framer-motion # >= 11.0.0 khuyến nghị ``` - [ ] **React Spring** — Kiểm tra `>= 9.x` - [ ] **GSAP** — Kiểm tra plugin compatibility ### 4.6 Styling - [ ] **Tailwind CSS** — Kiểm tra `>= 3.4.x`, Tailwind v4 đang trong beta ```bash npm ls tailwindcss ``` - [ ] **styled-components** — Kiểm tra `>= 6.x` cho React 19 Server Components > ⚠️ Lưu ý: styled-components không hoạt động với Server Components, chỉ dùng với `"use client"` - [ ] **Emotion** — Tương tự styled-components, chỉ Client Components - [ ] **CSS Modules** — Hoạt động tốt, không có breaking change ### 4.7 Authentication - [ ] **NextAuth.js (Auth.js)** — Migrate lên `>= 5.x` (Auth.js) ```bash npm ls next-auth # next-auth >= 5.0.0 (Auth.js) cho Next.js 15 ``` > ⚠️ NextAuth v5 có breaking changes lớn so với v4 - [ ] **Clerk** — Kiểm tra `@clerk/nextjs >= 5.x` - [ ] **Supabase Auth** — Kiểm tra `@supabase/ssr` package mới thay vì `@supabase/auth-helpers-nextjs` ### 4.8 Testing Libraries - [ ] **Jest** — Kiểm tra config tương thích với Next.js 15 ```bash npm ls jest @testing-library/react @testing-library/jest-dom # @testing-library/react >= 15.x cho React 19 ``` - [ ] **Playwright** — Kiểm tra `>= 1.40.x` - [ ] **Cypress** — Kiểm tra `>= 13.x` - [ ] **Vitest** — Kiểm tra `>= 1.x`, tương thích tốt - [ ] Cập nhật Jest config cho Next.js 15 ```js // jest.config.js const nextJest = require("next/jest"); const createJestConfig = nextJest({ dir: "./" }); module.exports = createJestConfig({ testEnvironment: "jsdom", setupFilesAfterFramework: ["/jest.setup.ts"], }); ``` ### 4.9 Kiểm Tra Tổng Quát - [ ] Chạy `npm audit` sau khi upgrade tất cả packages ```bash npm audit npm audit fix ``` - [ ] Kiểm tra `npm ls --depth=0` không có unmet peer dependencies - [ ] Test build production ```bash npm run build ``` - [ ] Kiểm tra bundle size không tăng đột biến ```bash npx @next/bundle-analyzer ``` --- ## 5. Testing Checklist Sau Migration ### 5.1 Build & Compile - [ ] `npm run build` thành công không có errors - [ ] Không có TypeScript errors: `npx tsc --noEmit` - [ ] Không có ESLint errors: `npm run lint` - [ ] Bundle size trong acceptable range - [ ] Kiểm tra `.next/` directory được generate đúng ### 5.2 Development Server - [ ] `npm run dev` khởi động thành công - [ ] Hot Module Replacement (HMR) hoạt động - [ ] Fast Refresh hoạt động khi edit components - [ ] Không có warnings về deprecated APIs trong console - [ ] Turbopack (nếu enable) không có compilation errors ### 5.3 Core Functionality Testing - [ ] **Navigation:** Tất cả internal links hoạt động đúng - [ ] **Dynamic routes:** `[slug]`, `[id]` params được resolve đúng - [ ] **Catch-all routes:** `[...slug]` hoạt động - [ ] **Query params:** `searchParams` được đọc đúng - [ ] **Redirects & Rewrites:** Kiểm tra `next.config.js` redirects - [ ] **Middleware:** Authentication, i18n middleware hoạt động ### 5.4 Data Fetching Testing - [ ] Server Components fetch data thành công - [ ] Cache/revalidate hoạt động đúng - [ ] `revalidatePath()` trigger đúng - [ ] `revalidateTag()` trigger đúng - [ ] ISR (Incremental Static Regeneration) hoạt động - [ ] Static pages được generate đúng ### 5.5 Forms & Mutations - [ ] Server Actions submit thành công - [ ] `useActionState` hiển thị đúng states (idle, pending, success, error) - [ ] `useFormStatus` hoạt động đúng - [ ] Form validation errors hiển thị đúng - [ ] Optimistic updates (nếu có) hoạt động ### 5.6 Authentication Flow - [ ] Login flow hoạt động - [ ] Logout flow hoạt động - [ ] Protected routes redirect đúng - [ ] Session persistence hoạt động - [ ] Cookie handling với async `cookies()` đúng ### 5.7 UI/UX Testing - [ ] Tất cả pages render đúng layout - [ ] Loading states hiển thị đúng - [ ] Error boundaries hoạt động - [ ] Responsive design không bị ảnh hưởng - [ ] Dark/Light mode (nếu có) hoạt động - [ ] Animations (Framer Motion, etc.) hoạt động mượt mà - [ ] Images load đúng với `next/image` - [ ] Fonts load đúng với `next/font` ### 5.8 Performance Testing - [ ] Chạy Lighthouse audit trên production build ```bash npx lighthouse https://your-site.com --view ``` - [ ] Kiểm tra Core Web Vitals không giảm - [ ] **LCP** (Largest Contentful Paint) < 2.5s - [ ] **FID/INP** (Interaction to Next Paint) < 200ms - [ ] **CLS** (Cumulative Layout Shift) < 0.1 - [ ] Kiểm tra không có memory leaks - [ ] Server response time trong acceptable range ### 5.9 SEO Testing - [ ] Meta tags render đúng (title, description) - [ ] Open Graph tags hoạt động - [ ] `robots.txt` accessible - [ ] `sitemap.xml` generated đúng - [ ] Canonical URLs đúng - [ ] Structured data (JSON-LD) không bị ảnh hưởng ### 5.10 Automated Tests - [ ] Tất cả unit tests PASS ```bash npm run test ``` - [ ] Integration tests PASS - [ ] E2E tests PASS ```bash npm run test:e2e ``` - [ ] Test coverage không giảm so với trước migration - [ ] Snapshot tests được update ```bash npm run test -- --updateSnapshot ``` ### 5.11 Cross-browser Testing - [ ] Chrome (latest) - [ ] Firefox (latest) - [ ] Safari (latest) — đặc biệt quan trọng với iOS - [ ] Edge (latest) - [ ] Mobile browsers (iOS Safari, Chrome Android) ### 5.12 Production Deployment Checklist - [ ] Environment variables đã được set đúng - [ ] Build production thành công trong CI/CD - [ ] Database migrations (nếu có) đã chạy - [ ] CDN cache invalidated - [ ] Monitoring/alerting setup kiểm tra OK - [ ] Rollback plan đã chuẩn bị - [ ] Deploy to staging trước, test xong mới production - [ ] Post-deployment smoke tests --- ## Tài Liệu Tham Khảo | Tài liệu | Link | |---|---| | Next.js 15 Migration Guide | [nextjs.org/docs/upgrading](https://nextjs.org/docs/upgrading) | | React 19 Upgrade Guide | [react.dev/blog/2024/04/25/react-19-upgrade-guide](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) | | Next.js Codemods | [nextjs.org/docs/app/building-your-application/upgrading/codemods](https://nextjs.org/docs/app/building-your-application/upgrading/codemods) | | React 19 Blog Post | [react.dev/blog/2024/12/05/react-19](https://react.dev/blog/2024/12/05/react-19) | | Next.js 15 Release Notes | [nextjs.org/blog/next-15](https://nextjs.org/blog/next-15) | --- ## Lệnh Codemod Tổng Hợp ```bash # Chạy tất cả codemods cần thiết (khuyến nghị) npx @next/codemod@canary upgrade latest # Hoặc chạy từng codemod riêng lẻ npx @next/codemod@canary next-async-request-api . # async params, cookies, headers npx @next/codemod@canary next-comp-link-passthrough-ref . # forwardRef → ref prop npx @next/codemod@canary new-link . # → npx @next/codemod@canary next-og-import . # OG image imports ``` --- > **💡 Tips:** > - Migrate từng breaking change một, commit sau mỗi bước để dễ debug > - Dùng `git bisect` nếu có regression khó tìm > - Enable React 19 strict mode để phát hiện sớm deprecated patterns > - Theo dõi [Next.js GitHub Discussions](https://github.com/vercel/next.js/discussions) để cập nhật issues mới nhất