</>
⌕
← Trang chủ
Nx

Next.js

App Router, RSC, caching, SSR/SSG, middleware

🃏 Ôn bằng flashcard
Tiến độ0/28 · 0%
Junior

App Router và Pages Router khác nhau thế nào? Có thể dùng song song không?

App Router (thư mục `app/`) dựa trên React Server Components, layout lồng nhau, streaming và Server Actions; Pages Router (`pages/`) dùng `getServerSideProps`/`getStaticProps` và mọi component mặc định là client. Hai router chạy song song được, nhưng một URL không được khai báo ở cả hai.

#app-router#pages-router#routing
Junior

Biến môi trường NEXT_PUBLIC_ khác biến thường như thế nào? Có thể đổi lúc runtime không?

Biến có tiền tố NEXT_PUBLIC_ được inline thẳng vào JS bundle của client lúc build, nên ai cũng đọc được và giá trị bị đóng băng sau build. Biến không có tiền tố chỉ tồn tại ở server (process.env lúc runtime) và là nơi để đặt secret.

#env#security#build-time
Junior

Dynamic route và generateStaticParams trong App Router dùng thế nào?

Thư mục `[slug]` tạo route động; `[...slug]` bắt nhiều đoạn, `[[...slug]]` bắt cả đường dẫn gốc. `generateStaticParams` trả danh sách param để pre-render lúc build. Từ Next 15, `params` là Promise nên phải `await`.

#dynamic-routes#ssg#generatestaticparams
Junior

layout, template, loading, error và not-found trong App Router dùng để làm gì?

layout giữ state và không remount khi điều hướng giữa các route con; template remount mỗi lần điều hướng. loading.tsx là fallback Suspense bọc page, error.tsx là Error Boundary (phải là Client Component), not-found.tsx hiển thị khi gọi notFound() hoặc không khớp route.

#layout#template#loading
Junior

Metadata API và SEO trong Next.js: generateMetadata, sitemap, robots, Open Graph?

Export `metadata` (tĩnh) hoặc `generateMetadata` (động, theo params) trong `layout`/`page` để Next sinh thẻ title, description, Open Graph, canonical. Thêm `sitemap.ts`, `robots.ts` và `opengraph-image` để hoàn thiện SEO; chỉ dùng được ở Server Component.

#seo#metadata#sitemap
Junior

next/image và next/font tối ưu hiệu năng như thế nào?

next/image tự resize, chuyển WebP/AVIF, lazy-load và dành sẵn chỗ (width/height hoặc fill) để tránh layout shift; priority cho ảnh LCP. next/font tải font lúc build, self-host cùng domain, dùng size-adjust fallback nên không có request tới Google và giảm CLS.

#next-image#next-font#performance
Junior

next/link prefetch hoạt động thế nào và điều hướng client-side khác gì reload trang?

`<Link>` điều hướng client-side (không reload) và tự prefetch route khi link vào viewport, chỉ ở production. Route tĩnh được prefetch đầy đủ; route dynamic chỉ prefetch tới `loading.tsx` gần nhất. Tắt bằng `prefetch={false}`.

#link#prefetch#navigation
Junior

Route group và private folder trong App Router dùng để làm gì?

Thư mục `(group)` gom route theo nhóm mà không đổi URL, cho phép mỗi nhóm có layout riêng. Thư mục `_private` bị loại khỏi routing, dùng để đặt code dùng chung ngay cạnh route (component, helper).

#route-groups#project-structure#app-router
Junior

Server Component và Client Component trong Next.js App Router khác nhau thế nào?

Trong App Router, mọi component mặc định là Server Component: chạy trên server, không gửi JS của nó xuống client, truy cập được DB/secret. Client Component (khai báo 'use client') dùng được state, effect, event handler và browser API, và được hydrate ở client.

#server-components#client-components#app-router
Mid

cookies(), headers() và Dynamic APIs: tác động đến rendering và thay đổi ở Next 15?

`cookies()`, `headers()`, `draftMode()` và `searchParams` là dynamic API: dùng chúng khiến route render theo từng request (dynamic). Từ Next 15 chúng bất đồng bộ nên phải `await`. Chỉ đọc ở Server Component; ghi cookie chỉ ở Server Action hoặc Route Handler.

#cookies#headers#dynamic-rendering
Mid

Data fetching trong App Router: khi nào fetch ở Server Component, khi nào dùng Route Handler?

Ưu tiên fetch/gọi DB trực tiếp trong Server Component (async/await), không cần API trung gian. Dùng Route Handler (route.ts) khi cần endpoint HTTP cho client ngoài, webhook hoặc proxy. Tránh waterfall bằng Promise.all hoặc tách thành các component riêng bọc Suspense.

#data-fetching#route-handlers#parallel-fetching
Mid

Form với Server Actions: useActionState, useFormStatus và progressive enhancement?

Truyền Server Action vào `action` của `<form>`; `useActionState` (React 19, trước là `useFormState`) giữ state trả về như lỗi validation, `useFormStatus` (phải nằm trong form con) cho biết `pending`. Form hoạt động cả khi chưa hydrate (progressive enhancement).

#server-actions#forms#react-19
Mid

Hydration error trong Next.js là gì, nguyên nhân phổ biến và cách sửa?

Hydration error xảy ra khi HTML do server render khác với kết quả render đầu tiên ở client. Nguyên nhân hay gặp: Date/Math.random/locale, truy cập window/localStorage khi render, HTML lồng sai (div trong p), extension trình duyệt. Sửa bằng useEffect/useState sau mount, hoặc suppressHydrationWarning.

#hydration#ssr#debugging
Mid

ISR và on-demand revalidation: revalidatePath và revalidateTag dùng thế nào?

ISR cập nhật trang tĩnh mà không build lại: `revalidate = N` (time-based) hoặc on-demand bằng `revalidatePath`/`revalidateTag` gọi từ Server Action hoặc Route Handler. Cơ chế là stale-while-revalidate: người dùng đầu tiên sau khi hết hạn vẫn nhận bản cũ.

#isr#revalidate#caching
Mid

Middleware trong Next.js chạy ở đâu, dùng làm gì và có những giới hạn nào?

Middleware chạy trước khi request tới route, mặc định ở Edge runtime, dùng để redirect, rewrite, set header/cookie, kiểm tra auth sơ bộ. Giới hạn: không có Node API (fs, nhiều driver DB), giới hạn kích thước bundle, thời gian chạy ngắn; nên dùng matcher để thu hẹp phạm vi.

#middleware#edge-runtime#auth
Mid

next/dynamic và phân tích bundle: giảm JavaScript gửi tới client thế nào?

`next/dynamic` lazy-load Client Component (code-splitting, tùy chọn `ssr: false`, `loading`). Đo bằng `@next/bundle-analyzer` để tìm thư viện nặng, rồi giữ logic ở Server Component, import theo module con và chỉ load khi cần.

#performance#bundle#code-splitting
Mid

Phân biệt SSG, SSR, ISR trong App Router; điều gì khiến một route thành dynamic?

Route mặc định static (render lúc build, SSG). Dùng cookies(), headers(), searchParams, fetch no-store hoặc export const dynamic = 'force-dynamic' thì thành dynamic (SSR mỗi request). ISR là static có revalidate (export const revalidate hoặc fetch next.revalidate) để tái tạo nền theo thời gian/tag.

#ssr#ssg#isr
Mid

redirects, rewrites và headers trong next.config khác nhau thế nào?

`redirects` trả 307/308 và đổi URL trên trình duyệt; `rewrites` giữ nguyên URL nhưng map sang đường dẫn/URL khác (hữu ích làm proxy API); `headers` thêm HTTP header cho response. Cả ba khai báo tĩnh, chạy trước filesystem routes, và hỗ trợ `has`/`missing` để match theo header, cookie, query.

#next-config#redirects#rewrites
Mid

Server Actions hoạt động thế nào và cần lưu ý gì về bảo mật?

Server Action là hàm async 'use server' mà Next biến thành endpoint POST công khai. Phải coi như API public: validate input (zod), kiểm tra authn/authz trong chính action, không tin dữ liệu client. Sau khi mutate gọi revalidatePath/revalidateTag để làm mới cache.

#server-actions#security#revalidatePath
Mid

Triển khai authentication/authorization trong App Router đúng cách như thế nào?

Lưu session trong cookie httpOnly, secure, sameSite. Middleware chỉ kiểm tra sơ bộ (optimistic) để redirect; kiểm tra thật phải đặt gần dữ liệu, trong Data Access Layer, Route Handler và Server Action. Không kiểm tra auth trong layout vì layout không re-render khi điều hướng.

#auth#session#data-access-layer
Senior

after() và instrumentation.ts dùng để làm gì trong Next.js?

`after()` (stable từ Next 15.1) lên lịch chạy code sau khi response đã gửi xong, phù hợp logging, analytics mà không làm chậm người dùng. `instrumentation.ts` export `register()` chạy một lần khi server khởi động để cắm monitoring như OpenTelemetry hoặc Sentry.

#after#instrumentation#observability
Senior

Deploy Next.js: Vercel khác self-host thế nào? Output standalone và Docker?

Vercel hỗ trợ sẵn ISR, Image Optimization, Edge/Middleware. Self-host dùng `next start` hoặc `output: "standalone"` để tạo `server.js` kèm đúng các dependency cần thiết, đóng gói Docker nhỏ gọn. Cần tự lo cache dùng chung giữa các instance, CDN cho `_next/static` và biến môi trường.

#deployment#docker#standalone
Senior

Giải thích 4 tầng cache của Next.js App Router và cách revalidate

Request Memoization (dedupe fetch trong một lần render), Data Cache (kết quả fetch, bền qua request/deploy), Full Route Cache (HTML + RSC payload của route static, trên server) và Router Cache (RSC payload trong bộ nhớ browser). Revalidate bằng revalidateTag/revalidatePath hoặc next.revalidate.

#caching#data-cache#full-route-cache
Senior

Kết hợp TanStack Query với Server Components: prefetch và HydrationBoundary?

Tạo `QueryClient` mỗi request ở server, `prefetchQuery` trong Server Component rồi bọc con bằng `<HydrationBoundary state={dehydrate(client)}>`. Client Component dùng `useQuery` cùng `queryKey` sẽ có data ngay và vẫn refetch/invalidate như thường. Đặt `staleTime` lớn hơn 0 để tránh refetch ngay.

#react-query#rsc#hydration
Senior

Parallel Routes và Intercepting Routes là gì? Làm modal có URL riêng thế nào?

Parallel Routes dùng thư mục @slot để render nhiều page độc lập trong cùng layout (nhận qua props). Intercepting Routes (.)/(..)/(...) chặn điều hướng client tới route khác và hiển thị nó trong ngữ cảnh hiện tại, ghép lại cho pattern modal vẫn có URL chia sẻ được, F5 thì ra trang đầy đủ.

#parallel-routes#intercepting-routes#modal
Senior

RSC payload là gì? 'use client' boundary ảnh hưởng thế nào đến bundle và cách tối ưu?

RSC payload là chuỗi mô tả cây React đã render của Server Component, kèm tham chiếu (module id, chunk) tới Client Component và props đã serialize. 'use client' tạo ranh giới: mọi module được import từ file đó đều vào client bundle. Giữ boundary ở lá, truyền Server Component qua children, lazy-load phần nặng.

#rsc-payload#use-client#bundle
Senior

Security headers và CSP với nonce trong Next.js được triển khai thế nào?

Header tĩnh (HSTS, X-Content-Type-Options, frame-ancestors...) đặt trong `headers()` của next.config. CSP chặt chẽ dùng nonce cho mỗi request: sinh trong Middleware, gắn vào header `Content-Security-Policy` và `x-nonce`; Next tự áp nonce cho script của nó. Đổi lại trang phải render dynamic.

#security#csp#middleware
Senior

Streaming với Suspense và Partial Prerendering (PPR) trong Next.js hoạt động ra sao?

Streaming gửi HTML theo từng phần: shell hiển thị ngay, phần chậm bọc trong Suspense được stream sau (loading.tsx là Suspense tự động cho cả page). PPR (experimental) prerender static shell lúc build, các 'hố' dynamic trong Suspense được stream theo request, kết hợp tốc độ static với dữ liệu động.

#streaming#suspense#ppr