← ProgrammingBack to top

Next.js: React full stack framework

Next.js is the Web framework based on React, providing routing, server-side rendering, static generation, data acquisition, caching, SEO and back-end capabilities.

Compared with ordinary React SPA, the most important new capabilities of Next.js are:

  • File system based App Router.
  • React Server Components。
  • SSR, SSG, ISR and other rendering strategies.
  • Server-side data acquisition and caching.
  • Metadata, Sitemap and other SEO functions.
  • Route Handlers and Server Actions.
  • Images, fonts and production build optimization.

1. Core concepts

moduleimportant conceptspriority
RoutingApp Router、Layout、Dynamic Routes、LinkMust learn
ComponentsServer Components、Client Components、use clientMust learn
RenderingSSR、SSG、CSR、HydrationMust learn
DataServer Fetching、Caching、RevalidationMust learn
SEOMetadata、Open Graph、SitemapMust learn
AssetsImage、Font、Static Assetsimportant
UXSuspense、Streaming、Loading、Errorimportant
BackendRoute Handlers、Server Actionson demand
ArchitectureISR、Cache Components、PPRAdvanced
DeploymentStatic Export、Node Server、Dockerimportant

The difference between Next.js and React + Vite

AbilityReact + Vite SPANext.js
React UIsupportsupport
Client routingUsually use React RouterBuilt-in App Router
CSRsupportsupport
SSRNeed additional solutionsBuilt-in
SSGNeed additional solutionsBuilt-in
React Server ComponentsDoes not belong to the default capabilities of ordinary Vite SPABuilt-in
API RoutesRequires independent backendRoute Handlers
SEO Metadataself-managementBuilt-in Metadata API
Image optimizationThird-party tools or self-implementationnext/image
Data cacheUsually managed by TanStack Query etc.Server cache + optional client cache
Production deploymentUsually static filesStatic files or Node.js Server

Next.js does not replace React, but adds routing, rendering, server-side functions and building conventions based on React.

2. Installation and project structure

Create project:

pnpm create next-app@latest my-site

Commonly used commands:

# development server
pnpm dev

# Production build
pnpm build

# Start production server
pnpm start

Typical project structure:

my-site/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   ├── globals.css
│   ├── loading.tsx
│   ├── error.tsx
│   ├── not-found.tsx
│   │
│   ├── about/
│   │   └── page.tsx
│   │
│   ├── blog/
│   │   ├── page.tsx
│   │   └── [slug]/
│   │       └── page.tsx
│   │
│   └── api/
│       └── health/
│           └── route.ts
│
├── components/
├── lib/
├── public/
├── next.config.ts
└── package.json

Among them:

  • app/: File system based routing.
  • components/: Reusable components.
  • lib/: Tool functions, data access, etc.
  • public/: Static resources.
  • next.config.ts: Next.js configuration.

3. App Router: File system routing

Next.js Define routes using files and folders.

For example:

app/
├── page.tsx
├── about/
│   └── page.tsx
└── blog/
    └── [slug]/
        └── page.tsx

Corresponds to:

/                 → app/page.tsx
/about            → app/about/page.tsx
/blog/react       → app/blog/[slug]/page.tsx
/blog/typescript  → app/blog/[slug]/page.tsx

special files

Filefunction
page.tsxDefine routing page
layout.tsxDefine shared layout
template.tsxLike Layout, but instances can be recreated while navigating
loading.tsxRoute loading status
error.tsxrouting error boundary
not-found.tsxNot Found UI
route.tsHTTP Route Handler
default.tsxParallel Routes defaults to UI

Layout

// app/layout.tsx

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <header>My Website</header>
        <main>{children}</main>
        <footer>Copyright</footer>
      </body>
    </html>
  );
}

Layout can be nested.

For example:

app/
├── layout.tsx
└── blog/
    ├── layout.tsx
    └── page.tsx

blog/layout.tsx only applies to the Blog route and its sub-routes.

Sharing Layout usually keeps the mount state alive while the client navigates, avoiding unnecessary re-rendering and state loss.

4. Dynamic Routes

Dynamic routes are defined using square brackets:

app/blog/[slug]/page.tsx

Visit:

/blog/react-basics

Corresponds to:

type Props = {
  params: Promise<{
    slug: string;
  }>;
};

export default async function BlogPage({ params }: Props) {
  const { slug } = await params;

  return <h1>{slug}</h1>;
}

In Next.js 15/16, params of App Router is Promise, which needs to be read asynchronously.

Catch-all Routes

[...slug]

For example:

/docs/react/hooks

Possible to get:

{
  slug: ["react", "hooks"];
}

Optional Catch-all Routes

[[...slug]]

Can match zero or more path fragments.

Next.js provides next/link:

import Link from "next/link";

export default function Navbar() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/blog">Blog</Link>
      <Link href="/about">About</Link>
    </nav>
  );
}

Main functions:

  • Client navigation.
  • Route prefetching.
  • Reduce unnecessary full page refreshes.
  • Works with App Router's client route cache.

useRouter

If you need to navigate within event handlers:

"use client";

import { useRouter } from "next/navigation";

export function NavigationButton() {
  const router = useRouter();

  return <button onClick={() => router.push("/blog")}>Open Blog</button>;
}

Commonly used methods:

methodfunction
router.push()Navigate and add history
router.replace()Navigate and replace history
router.back()Return to previous page
router.refresh()Request new server content for the current route
router.prefetch()Prefetch routing

router.refresh() does not mean clearing all server caches. If the data comes from a server-side cache that is still valid, you may still see the cached data after refreshing.

6. Server Components

In App Router, Page and Layout default to Server Component.

For example:

// app/blog/page.tsx

export default async function BlogPage() {
  const posts = await getPosts();

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Features of Server Component:

  • Execute in server environment.
  • Can directly access server-side databases, files or private API.
  • async/await can be used.
  • Does not send its own component implementation code to the browser as Client Component JavaScript.
  • You cannot directly use useState, useEffect and other clients Hook.
  • Browsers such as window, document and API cannot be accessed directly.

Value of Server Component

Browser Request
       ↓
Next.js Server
       ↓
Server Component
       ↓
Fetch Data
       ↓
Render RSC Payload / HTML
       ↓
Browser

This reduces the number of JavaScripts that the browser needs to perform and allows the data fetch to occur closer to the server resources.

Note: Server Component is executed on the server by default, which does not mean that it must be re-executed for every request; the actual behavior also depends on the pre-rendering and caching strategy.

7. Client Components

Use when browser interaction is required:

"use client";

import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);

  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

Client Component is suitable for:

  • useState、useEffect。
  • User interaction events.
  • React Hook Form。
  • TanStack Query Hooks。
  • Browser API.
  • Third-party components that require a browser environment.

The actual meaning of use client

"use client" declares client module boundaries.

The marked module and its static import dependencies will enter the client module graph.

But please note:

Client Component does not mean that the first screen is not generated by the server at all HTML.

Next.js can prerender the initial HTML of Client Component, and then the browser loads JavaScript and does Hydration.

BlogPage (Server Component)
    │
    ├── ArticleContent (Server Component)
    │
    ├── TableOfContents (Client Component)
    │
    └── LikeButton (Client Component)

Principles:

retains Server Component by default, and only divides the parts that require interaction into Client Component.

Don't randomly add "use client" to the entire page or root Layout just for convenience.

8. Combination of Server Component and Client Component

Server Component can import and render Client Component.

// app/blog/page.tsx
import LikeButton from "@/components/LikeButton";

export default async function BlogPage() {
  const post = await getPost();

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>

      <LikeButton postId={post.id} />
    </article>
  );
}

Client Component:

"use client";

import { useState } from "react";

export default function LikeButton({ postId }: { postId: number }) {
  const [liked, setLiked] = useState(false);

  return (
    <button onClick={() => setLiked(!liked)}>{liked ? "Liked" : "Like"}</button>
  );
}

When Server Component passes Props to Client Component, the data usually needs to meet the serialization requirements of React.

Ordinary functions cannot be transferred across the Server/Client boundary at will; Server Functions has a special transfer mechanism.

9. SSR、SSG、CSR、ISR

These four concepts mainly describe rendering and content update strategies.

modemeaningApplicable scenarios
CSRMainly render page content in the browserHighly interactive applications
SSRHTML is generated on the server when requestedLive or personalized content
SSGHTML is pre-generated at build timeBlogs, documents
ISRUpdate generated content by policy after deploymentRegularly updated pages

CSR

Browser
   ↓
Load HTML + JavaScript
   ↓
React Executes
   ↓
Fetch Data
   ↓
Render UI

Typical application: ordinary React SPA.

SSR

Browser
   ↓
Request Page
   ↓
Server Fetches Data
   ↓
Server Renders HTML
   ↓
Browser Receives HTML
   ↓
Hydration

Suitable for pages where the content needs to be determined at request time.

SSG

Build Time
    ↓
Generate HTML
    ↓
Deploy Static Files
    ↓
Browser

Suitable for less changing content such as blogs, documents, About pages.

ISR

Static Content
      ↓
Cache Lifetime / Revalidation
      ↓
Regenerate or Refresh
      ↓
Updated Content

Instead of simply rebuilding the entire website in the background at regular intervals, ISR uses the Next.js caching and revalidation mechanism to update the corresponding content.

In Next.js 16, the corresponding configuration model should be selected depending on whether Cache Components is used.

10. Hydration

Hydration means React takes over HTML provided by the server in the browser and establishes interactive capabilities.

Server Generated HTML
          ↓
Browser Displays HTML
          ↓
Download Client JS
          ↓
React Hydration
          ↓
Interactive UI

For example, the server has output:

<button>Count: 0</button>

After the browser completes Hydration, this button obtains the interactive behavior defined by React.

Hydration Mismatch

A Hydration error may occur if the HTML generated by the server is inconsistent with the first rendering result of the browser.

Common reasons:

  • The rendering stage reads window or localStorage directly.
  • The server and client output different times.
  • Use unfixed random values.
  • Inconsistent conditional rendering.
  • Invalid HTML nesting.

The principle is to ensure that the first round of server-side and client-side rendering results are consistent.

11. Server-side Data Fetching

Server Component can directly perform asynchronous operations.

export default async function BlogPage() {
  const response = await fetch("https://api.example.com/posts");

  if (!response.ok) {
    throw new Error("Failed to fetch posts");
  }

  const posts = await response.json();

  return <PostList posts={posts} />;
}

The difference between getting data from the client

Server Fetching:

Next.js Server
      ↓
External API / Database
      ↓
Server Component
      ↓
Rendered Result

Client Fetching:

Browser
    ↓
TanStack Query
    ↓
Axios / Fetch
    ↓
Backend API

Server Fetching suitable for:

  • Article content.
  • SEO related data.
  • Public data that needs to be displayed on the first screen.
  • You don't want to expose your private API credentials to the browser's data access.

Client Fetching suitable for:

  • Highly interactive data.
  • Data that needs to be continuously updated.
  • User action driven queries.
  • Local caching and optimistic updates.

The two can be mixed.

12. Next.js caching mechanism

Caching is a more complex part of App Router because different versions have different configuration models.

Need to distinguish:

cache typeMain function
Request MemoizationDeduplication within the same React server-side rendering
Server Data / Cache Components CacheReuse server-side data or component results between requests
Router CacheBrowser cache routing related RSC Payload
Browser HTTP CacheCache JS, CSS, pictures and other static resources

Request Memoization

In the same Server Component rendering, the same GET Fetch request can reuse the results.

const post1 = await fetch(url);
const post2 = await fetch(url);

Duplicate actual requests can be avoided when the same request conditions are met.

But it's not equivalent to persistent caching across HTTP requests.

Default fetch behavior

In modern Next.js App Router:

const response = await fetch(url);

Persistent data caching is not used by default.

If a page needs to reuse data across requests, an appropriate caching strategy needs to be adopted.

The following mainly introduces the Cache Components model of Next.js 16.

13. Cache Components

Enable:

// next.config.ts

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  cacheComponents: true,
};

export default nextConfig;

cacheComponents has access to the following abilities:

  • "use cache"。
  • cacheLife()。
  • cacheTag()。
  • revalidateTag()。
  • updateTag()。
  • Partial pre-rendering in collaboration with Suspense.

Cache Components does not mean that all content is automatically cached, but that the developer explicitly declares that it is suitable for reuse.

use cache

import { cacheLife } from "next/cache";

export default async function BlogPage() {
  "use cache";

  cacheLife("hours");

  const posts = await getPosts();

  return <PostList posts={posts} />;
}

What is cached here is the result of the function or component, not just a certain Fetch Response.

cacheLife

cacheLife("hours");

Used to declare cache life cycle.

Custom caching policies can also be configured.

cacheTag

import { cacheTag } from "next/cache";

export async function getPosts() {
  "use cache";

  cacheTag("posts");

  return fetchPostsFromDatabase();
}

Tag enables multiple related caches to be revalidated with the same identifier.

14. Revalidation: cache revalidation

Next.js 16 Cache Components provides several important methods.

revalidateTag

import { revalidateTag } from "next/cache";

revalidateTag("posts", "max");

Mark the relevant cache as expired and update it using the Stale-While-Revalidate pattern.

In other words, it is allowed to return the old content before performing a background refresh.

Suitable for content such as blogs and product catalogs that can tolerate short-term stale data.

updateTag

import { updateTag } from "next/cache";

updateTag("posts");

Immediately invalidate the relevant cache and the next read needs to get new data instead of continuing to return the old content.

updateTag() can only be used with Server Actions.

revalidatePath

import { revalidatePath } from "next/cache";

revalidatePath("/blog");

Revalidate relevant caches following routing paths.

Contrast

methodfunctionCommon uses
cacheLifeDefine cache lifecycleUpdate regularly
cacheTagTag cacheCache grouping
revalidateTagInvalidate and refresh in the backgroundBlog, content list
updateTagInvalid immediatelyInstant consistency after user submission
revalidatePathRe-verify by pathPage content update

The cache invalidation management here occurs on the Next.js server, which does not belong to the same cache system as TanStack Query's queryClient.invalidateQueries().

15. Suspense and Streaming

Next.js supports React Suspense and streaming rendering.

Suspense

import { Suspense } from "react";

export default function Page() {
  return (
    <main>
      <h1>Dashboard</h1>

      <Suspense fallback={<p>Loading...</p>}>
        <Analytics />
      </Suspense>
    </main>
  );
}

Allows waiting for asynchronous results to be placed separately into the load boundary.

Streaming

Browser Request
       ↓
Server
       │
       ├── Send Static HTML
       │
       ├── Send Loading UI
       │
       └── Send Async Content Later

This eliminates the need to wait for all data to be retrieved before sending the entire page.

loading.tsx

// app/blog/loading.tsx

export default function Loading() {
  return <p>Loading blog...</p>;
}

Next.js will establish a loading boundary for the corresponding route.

16. Error Handling

error.tsx

"use client";

export default function ErrorPage({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <p>Something went wrong.</p>
      <button onClick={reset}>Try again</button>
    </div>
  );
}

error.tsx is the routing segment error boundary and Client Component is required.

It is primarily intended to handle errors that can be caught by Error Boundary in the corresponding component tree, and is not meant to catch all types of server or event handling errors.

not-found.tsx

export default function NotFound() {
  return <h1>Page not found</h1>;
}

Cooperation:

import { notFound } from "next/navigation";

if (!post) {
  notFound();
}

The Not Found page can be displayed.

17. Metadata and SEO

Next.js provides Metadata API to facilitate the generation of SEO meta information for pages.

static Metadata

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "My Blog",
  description: "Articles about programming and technology",
};

Dynamic Metadata

import type { Metadata } from "next";

type Props = {
  params: Promise<{ slug: string }>;
};

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params;

  const post = await getPost(slug);

  return {
    title: post.title,
    description: post.summary,
  };
}

Suitable for dynamic blog posts.

Open Graph

export const metadata: Metadata = {
  title: "My Blog",
  openGraph: {
    title: "My Blog",
    description: "Programming articles",
    type: "website",
    images: ["/og-image.png"],
  },
};

Sitemap

// app/sitemap.ts

import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: "https://example.com",
      lastModified: new Date(),
    },
    {
      url: "https://example.com/blog",
      lastModified: new Date(),
    },
  ];
}

You can also use file conventions to generate robots.txt, Open Graph pictures, etc.

Note: SSR/SSG is helpful for search engines to directly obtain content, but it does not mean that using Next.js will automatically obtain a good SEO ranking.

18. generateStaticParams

Dynamic routing can use generateStaticParams() to pre-generate known pages during the build phase.

// app/blog/[slug]/page.tsx

export async function generateStaticParams() {
  const posts = await getPosts();

  return posts.map((post) => ({
    slug: post.slug,
  }));
}

For the Markdown or MDX blog, you can get the article Slug at build time and generate the corresponding page.

Markdown Files
      ↓
generateStaticParams()
      ↓
Known Slugs
      ↓
Static Blog Pages

This is very useful for personal blogs.

If pure static export is required, you must also ensure that all dynamic routes meet the restrictions of static export.

19. next/image

Next.js provides built-in Image components.

import Image from "next/image";

export default function Profile() {
  return <Image src="/avatar.jpg" alt="Avatar" width={300} height={300} />;
}

Main functions:

  • Responsive images.
  • Image size optimization.
  • Reduce layout offset.
  • Native Lazy Loading.
  • Provide optimized image resources according to the environment.

For remote pictures, the allowed remote sources need to be configured in next.config.ts.

Note: Default dynamic image optimization usually requires a running environment that supports image optimization. When exporting purely statically, you should use custom Loader or turn off built-in optimization and other compatible methods.

20. next/font

Next.js supports font loading and optimization.

For example:

import { Geist } from "next/font/google";

const geist = Geist({
  subsets: ["latin"],
});

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={geist.className}>{children}</body>
    </html>
  );
}

Main values:

  • Optimize font loading.
  • Reduce unnecessary font network requests.
  • Reduce layout shift caused by font switching.
  • Supports build-time self-hosting of font resources.

21. Route Handlers

Next.js can be defined using route.ts to define HTTP API.

For example:

// app/api/health/route.ts

export async function GET() {
  return Response.json({
    status: "ok",
  });
}

Corresponds to:

GET /api/health

You can also use POST:

export async function POST(request: Request) {
  const body = await request.json();

  return Response.json({
    received: body,
  });
}

Route Handlers supports common HTTP methods:

GET
POST
PUT
PATCH
DELETE
HEAD
OPTIONS

Relationship with Django DRF

If the project already uses Django REST Framework as the backend:

Next.js Frontend
       ↓
Django DRF API
       ↓
PostgreSQL

It is not necessarily necessary to rewrite a set of API through Next.js Route Handlers.

Route Handlers can be used for:

  • Lightweight backend interface.
  • Webhook。
  • Some server-side proxy or aggregation.
  • Next.js exclusive server function.

22. Server Actions / Server Functions

Server Actions allows client interaction to trigger server functions.

For example:

// app/actions.ts

"use server";

export async function createPost(formData: FormData) {
  const title = formData.get("title");

  // Validate input and check authorization
  // Save post to database
}

Form:

import { createPost } from "./actions";

export default function PostForm() {
  return (
    <form action={createPost}>
      <input name="title" />
      <button type="submit">Create</button>
    </form>
  );
}

Execution process:

Browser Form
      ↓
Server Action
      ↓
Validation / Authorization
      ↓
Database / Backend API
      ↓
Revalidation
      ↓
Updated UI

Server Actions is suitable for processing form submission, data modification and other operations.

Need to pay attention to:

  • Server Actions is not an ordinary front-end function.
  • Client calls trigger server communication.
  • Server-side validation and permission checks must be performed.
  • You should not assume that functions are inherently safe as long as they are written in a server file.
  • Not suitable as a replacement for all legacy HTTP API.

If you already have a complete API architecture of Django + Orval + TanStack Query, there is no need to force migration to Server Actions.

23. proxy.ts

In Next.js 16, proxy.ts replaces the old Middleware file naming convention.

For example:

// proxy.ts

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function proxy(request: NextRequest) {
  return NextResponse.next();
}

Can be used for:

  • Request redirect.
  • URL rewrite.
  • Some access control pre-logic.
  • Routing is performed based on the request information.

However, it is not recommended to perform a large number of complex database operations in Proxy.

In addition, the front-end permission check in Proxy cannot replace the real authentication and authorization in the backend.

For example, interfaces involving user private data must still verify permissions in the actual server-side processing logic.

24. Turbopack

Turbopack is the build tool for Next.js.

Key goals include:

  • Speed up development server startup.
  • Improve incremental compilation efficiency.
  • Reduce update feedback time for large projects.
  • Supports development and production build processes for Next.js.

It and Vite are both construction tool-related technologies, but the service framework ecology and implementation methods are different.

React + Vite
    ↓
Vite Build Pipeline

Next.js
    ↓
Turbopack

Next.js 16 has made Turbopack the default builder for development and production builds.

Some projects that require special build configurations still need to check plugin and build compatibility.

25. Static Export

Next.js can be built as a static website.

Configuration:

// next.config.ts

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
};

export default nextConfig;

Execution:

pnpm build

Typically generates:

out/
├── index.html
├── about.html
├── blog/
└── _next/
    └── static/

It can then be handed to Nginx, object storage, or CDN.

Limitations of Static Export

Purely static exports do not support functions that depend on the server performing the request, such as:

  • Dynamic SSR.
  • Server Actions。
  • Route Handlers requiring server processing.
  • Read the dynamic page of Cookie/Header on request.
  • Dynamic image optimization relying on Next.js server.
  • Proxy。

But Server Components does not necessarily mean that the Node.js server is required to run for a long time.

Server Components can still participate in static pre-rendering if the required data is available at build time.

26. Node.js Server and Docker

If you need SSR, Server Actions, dynamic data and other functions, you can deploy Node.js server.

Start:

pnpm build
pnpm start

It is also possible to configure the Standalone output:

// next.config.ts

const nextConfig = {
  output: "standalone",
};

export default nextConfig;

Standalone produces output more suitable for standalone server deployments.

Typical architecture:

Browser
    ↓
Nginx
    ↓
Next.js Node Server
    │
    ├── Server Components
    ├── Route Handlers
    ├── Server Actions
    └── Static Assets

If Django is used simultaneously:

Browser
    ↓
Nginx
    │
    ├── /       → Next.js
    │
    └── /api/   → Django DRF

Docker deployment

Multi-stage Dockerfile can be used:

Stage 1: Install Dependencies
           ↓
Stage 2: Next.js Build
           ↓
Stage 3: Production Runtime

If static export is used, the final image can only contain Nginx.

If dynamic server rendering is used, the Node.js runtime environment or other supported deployment platform is required.

27. Next.js and TanStack Query

The server-side data acquisition of Next.js and TanStack Query are not mutually exclusive.

Server Component

Suitable for directly obtaining server data:

export default async function Page() {
  const posts = await getPosts();

  return <PostList posts={posts} />;
}

Client Component

Good for content that requires interactivity and client-side caching:

"use client";

function Profile() {
  const { data } = useUserProfileRetrieve();

  return <div>{data?.username}</div>;
}

Selection principles

scenePrioritize
Blog post textServer Component
SEO contentServer Fetching
Public, more stable dataServer Cache
Profile editingClient Component + RHF
Complex filter searchTanStack Query
Optimistic updateTanStack Query
form submissionServer Actions or Mutation
real-time interactive dataClient Fetching / Subscribe

There is no need to delete the existing TanStack Query just because Next.js is adopted.

But there is no need to change all Server Components to Client Components in order to use TanStack Query.

28. Next.js FAQ

Q1: Does Next.js completely replace React Router?

For Next.js projects using App Router, React Router is generally no longer required.

Because Next.js already provides file system routing and client navigation.

Q2: Does the Next.js page default to all SSR?

no.

The page may be pre-rendered, dynamically rendered, partially pre-rendered, or may include client-side rendering.

We cannot simply think that Next.js = SSR.

Q3: Is Server Component necessarily faster than Client Component?

uncertain.

Server Component can usually reduce the client JavaScript, but may also increase the waiting time for server calculation and data acquisition.

Actual performance depends on content type, caching strategy, network conditions, and component structure.

Q4: Can Server Component be used with React Hook Form?

React Hook Form which relies on client Hook cannot be used directly.

The form should be placed in Client Component.

Q5: Is Next.js suitable for purely static personal blogs?

Suitable.

Can be combined with:

  • MDX。
  • App Router。
  • generateStaticParams。
  • Metadata。
  • Static Export。

But if the website is mainly purely static content, you can also consider tools that are more focused on content sites such as Astro and Hugo.

Q6: Does Next.js require a separate backend?

no.

Next.js provides Route Handlers and Server Actions.

But if the project already has a complete backend like Django DRF, Next.js can focus on front-end rendering and SEO, without having to repeatedly build the same business backend.

Summary

The core knowledge of Next.js can be divided into four levels:

levelcore concepts
basic routingApp Router、Layout、Dynamic Routes、Link
render modelServer Component、Client Component、SSR、SSG、Hydration
Data and cachingServer Fetching、use cache、cacheLife、Revalidation
Engineering capabilitiesMetadata、Streaming、Route Handlers、Server Actions、Deployment

Recommended learning order:

  1. App Router and file routing.
  2. Server Components and Client Components.
  3. SSR, SSG, CSR and Hydration.
  4. Server-side Data Fetching。
  5. Metadata and SEO.
  6. Suspense, Streaming and Error Handling.
  7. Cache Components and Revalidation.
  8. Route Handlers、Server Actions。
  9. Static Export, Docker and production deployments.

The core architecture can be summarized as:

React Components
       ↓
Next.js App Router
       │
       ├── Server Components
       │       ├── Data Fetching
       │       ├── Server Cache
       │       └── HTML / RSC Payload
       │
       └── Client Components
               ├── React Hooks
               ├── User Interaction
               ├── React Hook Form
               └── TanStack Query
                        ↓
                 Backend API

The main value of Next.js is not to allow all React code to run on the server, but to allow developers to choose the appropriate server-side and client-side rendering methods based on data, interaction, caching and SEO needs.


Reference documentation