Tổng hợp 92 câu hỏi phỏng vấn Next.js kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
Sự khác biệt chính bao gồm: - Kiến trúc (Architecture): App Router (Next.js 13+) dùng thư mục app/ và hỗ trợ React Server Components mặc định. Pages Router dùng thư mục pages/ nơi mọi component được xử lý như Client Component. - Data Fetching: App…
File-based routing trong Next.js App Router là cơ chế biến cấu trúc thư mục và file bên trong app/ thành URL của ứng dụng mà không cần khai báo route thủ công. Mỗi thư mục con là một route segment, và một segment chỉ trở…
Layout là UI chia sẻ giữa nhiều pages, preserve state khi navigate (không remount). layout.tsx nhận children prop. Nested layouts: layout lồng trong layout tạo hierarchy. Root layout (app/layout.tsx) bắt buộc phải có, wrap toàn app. Khác với template.tsx: template remount mỗi navigate.
loading.tsx tự động tạo Suspense boundary bọc page hoặc layout, hiển thị loading UI ngay lập tức khi navigate. Streaming: Next.js stream HTML từng phần, user thấy nội dung nhanh hơn thay vì đợi toàn trang. Instant loading states không cần manually thêm Suspense và…
error.tsx phải là Client Component, nhận error và reset props, hiển thị khi có lỗi trong segment. not-found.tsx hiển thị khi gọi notFound() từ server component hoặc khi URL không match route nào. Global error.tsx ở root app/ bắt lỗi kể cả trong root layout.
Route Groups dùng ngoặc đơn (groupName) để tổ chức routes mà không ảnh hưởng URL. Ví dụ: (auth)/login và (auth)/register share cùng layout auth nhưng URL vẫn là /login và /register. Useful để: apply layout cho subset of routes, organize large codebases theo features.
Dynamic routes trong App Router sử dụng cú pháp folder name trong ngoặc vuông, ví dụ app/blog/[slug]/page.tsx sẽ match URL /blog/anything. Next.js 15: params là Promise — cần const { slug } = await params trong async Server Component, hoặc React.use(params) trong Client Component. Catch-all…
Metadata trong App Router là API khai báo để Next.js tự sinh các thẻ trong <head như title, description, openGraph, robots. Bạn định nghĩa nó bằng cách export const metadata cho giá trị tĩnh hoặc export async function generateMetadata() cho giá trị động, đặt trong…
generateStaticParams export từ trang dynamic route để pre-generate static path lúc build, tương đương getStaticPaths bên Pages Router. Kết hợp với Static Generation để dựng sẵn trang tĩnh cho mọi giá trị tham số có thể có.
React Server Components (RSC) là các component chỉ chạy và render trên server. Đặc điểm chính: - Zero Bundle Size: Không gửi JavaScript code của chúng xuống client. - Truy cập trực tiếp Backend: Có thể gọi database, file system trực tiếp. - Bất đồng…
'use client' đặt ở đầu file để đánh dấu component là Client Component. Cần thiết khi component dùng: useState, useEffect, event handlers, browser APIs. Đặt boundary tại component cần interactivity, không cần wrap toàn app.
Server Component có thể import và render Client Component - đây là hướng dependency bình thường. Ngược lại: Client Component KHÔNG thể import Server Component vì server component sẽ bị client-ize. Nhưng Server Component có thể truyền Server Component làm children/props cho Client Component (pattern…
Server Component khi cần: data fetching, access backend resources, keep sensitive info (API keys), reduce client bundle. Client Component khi cần: onClick, onChange event handlers, useState/useEffect, browser APIs, real-time updates, custom hooks. Default là Server, chỉ dùng 'use client' khi thực sự cần interactivity.
Context API không hoạt động trong Server Components vì context phụ thuộc React runtime trên client. Chỉ Client Components mới có thể dùng Context. Để share data trong Server Components, truyền qua props hoặc dùng Next.js built-ins. Tạo Context Provider là Client Component và wrap…
Nhiều npm packages cũ dùng browser APIs hay React client features mà không có 'use client'. Giải pháp: tạo wrapper Client Component import library đó, thêm 'use client' ở wrapper. Next.js có boundary tự động cho packages với 'use client' trong package.json exports. Kiểm tra…
server-only và client-only là hai package nhỏ của Next.js dùng để đánh dấu rõ ràng một module chỉ được chạy ở một môi trường, giúp trình biên dịch báo lỗi ngay khi bạn import nhầm. server-only chặn việc import module vào client bundle; client-only chặn…
SSR (Server-Side Rendering) là phương thức render HTML trên server tại thời điểm request, rồi gửi HTML đã hoàn thiện về cho browser. Browser nhận được nội dung có thể hiển thị ngay mà không cần chờ JavaScript chạy xong trên client. Bạn có thể…
SSG tạo HTML tại build time, serve static files từ CDN. Nhanh vì chỉ trả file tĩnh, không cần server xử lý mỗi request. Phù hợp cho: blog, documentation, marketing pages, data ít thay đổi. Pages Router: không có getServerSideProps. App Router: dùng export const…
ISR kết hợp SSG và SSR: trang được generate tĩnh, nhưng sau revalidate seconds có thể regenerate lại. User đầu tiên sau revalidate nhận stale content, trigger background regeneration; user sau nhận fresh content. - Pages Router: return { revalidate: 60 } trong getStaticProps. -…
On-demand revalidation cho phép invalidate cache và regenerate pages ngay lập tức thay vì đợi timeout. - Pages Router: res.revalidate('/path') trong API route. - App Router: revalidatePath('/path') hoặc revalidateTag('posts') trong Server Action hoặc Route Handler. Phù hợp khi CMS webhook trigger cần update content ngay.
Next.js extend native fetch với caching: - fetch(url) mặc định no-store từ Next.js 15+ (trước đó cache). - { cache: 'force-cache' } để opt-in cache. - { next: { revalidate: 60 } } revalidate sau 60 giây. - { next: { tags: ['posts'] } }…
- Static rendering: render lúc build time, cache và serve từ CDN. - Dynamic rendering: render mỗi request, không cache. Tự động dynamic khi dùng: await cookies(), await headers(), searchParams, hay fetch với cache: 'no-store'. Explicit: export const dynamic = 'force-dynamic' hoặc 'force-static'. Opt-in static…
getStaticProps chạy tại build time, data embed vào static HTML, tốc độ cực nhanh, tốt cho data ít thay đổi. getServerSideProps chạy mỗi request, data luôn fresh, nhưng chậm hơn vì phải đợi server. Cả hai chỉ có trong Pages Router. App Router thay thế…
Streaming SSR gửi HTML từng phần xuống browser ngay khi ready thay vì đợi toàn trang. Dùng HTTP chunked transfer encoding. Kết hợp với Suspense: phần ngoài Suspense stream trước, phần trong stream khi data ready. Giảm Time to First Byte và First Contentful Paint.…
Route Handlers là cách tạo API endpoints trong App Router bằng cách đặt file route.ts trong thư mục app/. Mỗi HTTP method được export dưới dạng named function riêng biệt. Sử dụng Web APIs chuẩn (Request/Response) thay vì req/res của Node.js.
Server Actions là async functions chạy trên server, được gọi từ Client Components hoặc forms. Khai báo với 'use server' directive. Cho phép mutate data trực tiếp mà không cần tạo API endpoint riêng.
Gán Server Action vào form action attribute: <form action={createPost}. Form submit tự động gọi Server Action với FormData. Không cần JavaScript client-side (progressive enhancement). Trong action: const title = formData.get('title'). Kết hợp với useFormState (React 18) hoặc useActionState (React 19) để track state.
Sau khi mutate data trong Server Action, cần revalidate cache để UI cập nhật: revalidatePath('/posts') invalidate cached route, revalidateTag('posts') invalidate theo tag. redirect('/path') để điều hướng sau action thành công.
Server Actions có thể throw errors sẽ được catch bởi nearest error.tsx. Với useFormState/useActionState, return error object thay vì throw: return { error: 'Invalid input' }. Dùng try/catch trong action để handle expected errors (validation, not found) và return user-friendly error states.
Middleware là middleware.ts ở root, chạy trên Edge runtime trước mọi request. Dùng để: authentication/authorization, redirect, rewrite URL, add/modify headers, A/B testing. Return NextResponse để điều khiển response. Dùng matcher config để chỉ định routes áp dụng. Nhẹ và nhanh vì Edge runtime.
Import từ next/headers, cả hai đều là async kể từ Next.js 15+: const cookieStore = await cookies() và const headersList = await headers(). Đọc cookie: cookieStore.get('session'), cookieStore.set('session', value). Đọc header: headersList.get('user-agent'). Trong Server Components: read-only. Trong Server Actions và Route Handlers: có thể read và…
useOptimistic (React 19) kết hợp với Server Actions: cập nhật UI ngay trước khi action hoàn thành, rollback nếu fail. const [optimistic, addOptimistic] = useOptimistic(data, updateFn). Trong action handler: addOptimistic(newItem) trước await serverAction(). Tạo snappy UX dù có network latency.
next/image tự động: resize và optimize images theo viewport, serve WebP/AVIF modern formats, lazy load mặc định, prevent Cumulative Layout Shift (CLS) với width/height hoặc fill. Cần cung cấp width và height hoặc fill prop. Cấu hình allowed domains trong next.config. Tích hợp CDN support…
next/font tự động: download Google Fonts tại build time (không request runtime đến Google), host fonts trên cùng server, zero layout shift với automatic size adjustment, privacy tốt hơn. Dùng: import { Inter } from 'next/font/google'; const inter = Inter({ subsets: ['latin'] }). Apply qua…
Next.js tự động prefetch routes khi Link component vào viewport (production). Tải JS chunk và data cho route đó trước khi user click, tạo instant navigation. Disable: <Link prefetch={false}. App Router prefetch RSC payload. Control cụ thể: prefetch attribute hoặc router.prefetch(). Giúp navigation cảm giác…
next/script tối ưu loading third-party scripts. Strategies: beforeInteractive (trước hydration, cho critical scripts), afterInteractive (sau hydration, default), lazyOnload (idle time), worker (web worker với Partytown). Tránh dùng thẻ script thông thường trong App Router, dùng next/script thay thế.
Middleware có thể rewrite requests đến API khác: NextResponse.rewrite(new URL('/api/proxy', request.url)). Hoặc trong next.config.js dùng rewrites array để proxy: { source: '/api/:path', destination: 'https://backend.com/:path' }. Hữu ích để: hide API endpoints, implement BFF (Backend For Frontend), avoid CORS issues.
Next.js tối ưu: LCP (Largest Contentful Paint) qua image optimization, priority images; CLS (Cumulative Layout Shift) qua next/image với dimensions, next/font với size-adjust; INP (Interaction to Next Paint, thay FID từ 3/2024) qua code splitting, lazy loading, Concurrent Mode. Dùng @vercel/analytics (không phải next/analytics) để…
.env.local cho local development (git-ignored). .env.production, .env.development cho môi trường cụ thể. NEXTPUBLIC prefix expose biến xuống client bundle - KHÔNG đặt secrets với prefix này. Không có prefix: chỉ server-side. Trong App Router: server components đọc trực tiếp process.env.VAR. Client: chỉ NEXTPUBLIC vars.
Vercel là hãng tạo ra Next.js nên là nền tảng chạy Next.js ít phải cấu hình nhất: push code lên Git → Vercel build và deploy tự động. Vercel làm sẵn cho bạn: - Server Components / SSR / Route Handlers chạy trên Serverless/Edge Functions…
Cách mặc định: next build rồi next start chạy một Node server phục vụ cả static assets lẫn SSR/Route Handlers. Bạn đặt nó sau reverse proxy (Nginx) và cần cả thư mục .next lẫn toàn bộ nodemodules. Vấn đề: copy nguyên nodemodules (hàng trăm MB)…
Mục tiêu: image nhỏ, build cache tốt, không kéo theo devDependencies vào runtime. Cách chuẩn là multi-stage build kết hợp output: 'standalone'. Tại sao multi-stage: stage cuối chỉ lấy standalone (đã trace dependency) → image chỉ vài chục MB, không có source code hay devDeps.…
output: 'export' build app thành HTML/CSS/JS tĩnh thuần trong thư mục out/, deploy được lên bất kỳ static host nào (S3, GitHub Pages, Nginx) — không cần Node server. Hình dung: giống xuất một website ra file rồi bê đặt lên ổ đĩa — không…
CSS Modules và Tailwind xử lý style lúc build (compile ra file CSS tĩnh) → chạy được ngay với Server Components, không cần JS runtime ở client. Đây là lựa chọn khuyến nghị cho App Router. CSS-in-JS runtime (styled-components, Emotion) sinh CSS lúc render bằng…
Next.js cung cấp helper next/jest để tự lo cấu hình (transform SWC, mock CSS/ảnh, env). Dùng cho unit / component test: render Client Component bằng RTL, query theo role, fire event. Tại sao async Server Components là vấn đề: chúng là async function trả Promise…
Playwright chạy app trong trình duyệt thật (Chromium/Firefox/WebKit), nên nó test đúng những gì người dùng thấy — kể cả Server Components, streaming, Server Actions mà unit test không chạm tới được. Hình dung: Playwright là một con bot mở browser, click và đọc DOM…
Trong Pages Router đây là 2 file đặc biệt: - app.tsx — wrap mọi page, là nơi đặt layout chung, global CSS, provider (theme, store) và giữ state qua các lần điều hướng. Chạy cả server lẫn client. - document.tsx — tuỳ biến cấu trúc…
Cả hai làm mới Data Cache trên server sau khi data đổi (thường gọi trong Server Action / Route Handler). Khác nhau ở đơn vị nhắm tới. revalidatePath(path) — làm mới cache theo đường dẫn route. Dùng khi bạn biết rõ trang nào bị ảnh…
App Router không có i18n config sẵn như Pages Router; bạn dựng routing bằng dynamic segment [locale] + middleware để phát hiện/redirect ngôn ngữ. Middleware đọc Accept-Language hoặc cookie, redirect / → /vi. generateStaticParams liệt kê các locale để build tĩnh. next-intl xây sẵn lớp…
Hai hook bổ sung cho nhau khi làm form bằng Server Actions: useActionState (React, dùng ở Client Component) — bọc một action, giữ state trả về của nó (lỗi validation, kết quả) qua các lần submit. useFormStatus (react-dom) — cho biết form cha đang pending…
Draft Mode cho phép biên tập viên xem trước bản nháp từ CMS trên trang vốn được render tĩnh (SSG/ISR) — tức là bỏ qua cache, fetch nội dung chưa publish. Cơ chế: một Route Handler gọi draftMode().enable(), Next.js đặt một signed cookie; khi cookie…
'use client' không phải nhãn cho một file, nó đánh dấu ranh giới giữa hai đồ thị module. Mọi thứ được import từ file đó trở xuống đều bị coi là client và đi vào bundle gửi cho trình duyệt. Đặt ở layout gốc thì…
Sẽ gặp lỗi kiểu Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Lý do: props qua ranh giới server → client phải serialize được để nhúng vào payload RSC. React hỗ trợ primitive, plain…
Cả hai đều bọc route con, khác nhau ở vòng đời khi điều hướng: - layout.tsx: giữ nguyên instance khi chuyển giữa các route con. State bên trong không mất, effect không chạy lại, DOM không remount. - template.tsx: tạo instance mới mỗi lần điều…
Không, trong cùng một lượt render server chỉ có một request thực sự đi ra. Đây là request memoization: React ghi nhớ kết quả fetch theo (URL + options) trong suốt vòng đời của một request, các lời gọi sau lấy lại kết quả đã…
Vì error.tsx được render bên trong layout cùng cấp. Layout đã hỏng thì không thể bọc được UI lỗi của chính nó. Cách xử lý: - Lỗi ở app/dashboard/layout.tsx → cần app/error.tsx ở cấp cha bắt. - Lỗi ở layout gốc (app/layout.tsx) hoặc template gốc…
Đây là các hằng export ở đầu page.tsx/layout.tsx/route.ts để ép hành vi render và cache của cả segment. - dynamic: 'auto' (mặc định) · 'force-dynamic' render lại mỗi request, tương đương opt-out toàn bộ cache · 'force-static' ép static, các dynamic API như cookies() trả…
Hai thứ giải quyết hai bài toán khác nhau. Server Action — mutation phát sinh từ chính UI của app: - Gắn thẳng vào <form action={...} hoặc gọi từ client component, không phải tự viết fetch và endpoint. - Chạy được cả khi JS chưa…
Không bắt buộc. generateStaticParams chỉ quyết định tập được prerender lúc build; phần còn lại có thể render lần đầu khi có người truy cập rồi được cache lại. Chiến lược thường dùng: build sẵn nhóm quan trọng, phần đuôi dài để on-demand. Với dynamicParams…
Next.js cho phép pages/ và app/ cùng tồn tại trong một dự án, nên có thể chuyển dần từng phần thay vì viết lại một lượt. Khi trùng đường dẫn, app/ được ưu tiên. Thứ tự thường làm: 1. Nâng Next lên bản hỗ trợ,…
Next.js chia biến môi trường làm hai nhóm rất rõ: - Không có tiền tố (DATABASEURL, STRIPESECRETKEY): chỉ tồn tại ở phía server — Server Component, Route Handler, Server Action. Đọc ở client sẽ ra undefined. - Có NEXTPUBLIC (NEXTPUBLICGAID): được thay thế thẳng vào…
Khác biệt nằm ở chỗ URL trên thanh địa chỉ có đổi hay không. - redirects: server trả về mã 3xx, trình duyệt đi tới URL mới, thanh địa chỉ đổi. Người dùng và Google đều biết trang đã chuyển. - rewrites: server âm thầm…
Lỗi đó là cơ chế bảo vệ: nếu cho phép tối ưu ảnh từ mọi domain, ai cũng có thể ép server của bạn xử lý ảnh của họ. Phải khai báo domain được phép: Khai báo càng hẹp càng tốt (pathname, port). Tránh hostname:…
Lỗi xảy ra vì Next.js render component đó trên server (Node), nơi không có window/document. Thư viện chart, editor, map thường chạm vào DOM ngay khi import. ssr: false bảo Next.js bỏ qua component này trong lần render server, chỉ mount ở client. Kèm theo…
Ba nguyên nhân chiếm phần lớn trường hợp: 1. URL ảnh là đường dẫn tương đối. Crawler mạng xã hội cần URL tuyệt đối. Khai báo metadataBase một lần ở root layout, Next.js sẽ tự nối tiền tố: Thiếu metadataBase, thẻ sinh ra là /og.png…
Không. Chuẩn sitemap giới hạn 50.000 URL hoặc 50MB (chưa nén) mỗi file. Vượt ngưỡng thì Google bỏ qua phần dư. Ngoài ra, dựng một mảng 200.000 phần tử trong một hàm còn dễ hết bộ nhớ lúc build hoặc timeout lúc request. Cách đúng…
App Router bỏ cấu hình i18n tự động và yêu cầu bạn tự dựng routing bằng một dynamic segment: Ba phần cần ghép: 1. Middleware chọn ngôn ngữ. Khi vào / không có locale, đọc Accept-Language hoặc cookie đã lưu rồi redirect sang /vi hoặc…