Next.js: Introduction to Next.js 16

Next.js 16 is the latest version of Vercel’s full-stack React framework—it integrates file-system routing, server-side rendering, static generation, incremental static regeneration, and partial pre-rendering into a single development framework, making full-stack development simple.

This tutorial is designed for front-end developers with a basic understanding of React. It starts with the basics of the App Router and takes you all the way to building production-ready full-stack applications with Next.js 16.

1. What You'll Learn



2. A True Story of a Full-Stack Developer

(1) Pain Point: Performance Bottlenecks in React SPA Projects

Alice is a full-stack developer at a SaaS company who maintains a React SPA task management platform with 50,000 daily active users. Recently, she encountered three challenging problems:

Issue Impact Data
Slow first-screen load High bounce rate 3.2s FCP / 6.8s LCP
Poor SEO Google cannot index dynamic content 0 search results displayed
Low code reuse Separate sets of data logic written for front-end and back-end 40% code duplication

She tried React Helmet, lazy loading, and code splitting, but she was still unable to resolve the SEO issues in a pure SPA architecture.

(2) The Next.js Solution

Rewriting the app using the Next.js 16 App Router—Server Components for server-side rendering + PPR static shell + use cache smart caching.

TSX
// app/dashboard/page.tsx — Server Component Default
export default async function DashboardPage() {
  const tasks = await fetch('https://api.example.com/tasks');
  const projects = await fetch('https://api.example.com/projects');

  return (
    <div className="grid grid-cols-2 gap-4">
      <TaskSummary tasks={tasks} />
      <ProjectList projects={projects} />
    </div>
  );
}

(3) Revenue

Metric Before the refactoring (React SPA) After the refactoring (Next.js 16)
FCP 3.2s 0.8s
LCP 6.8s 1.5s
Number of SEO Pages 0 200+
Code Duplication Rate 40% 5%


3. What Is Next.js?

(1) Definition

Next.js is a React-based full-stack web development framework that was open-sourced by Vercel in 2016. It offers out-of-the-box features such as file-system routing, server-side rendering (SSR), static site generation (SSG), and API routing, enabling developers to build full-stack applications using React.

100%
graph TB
    A[Next.js 16] --> B[App Router<br/>File System Routing]
    A --> C[Rendering Engine<br/>SSR/SSG/ISR/PPR]
    A --> D[Data Collection<br/>Server Components]
    A --> E[API Routes<br/>Route Handlers]
    A --> F[Build Tools<br/>Turbopack]
    A --> G[Ecological Integration<br/>Auth/DB/Cache]

    style A fill:#cce5ff
    style B fill:#d4edda
    style C fill:#d4edda
Core Competency Description Problem Solved
File System Routing File names serve as URL paths No manual routing configuration required
Server Components Server-side rendering with zero-client JavaScript Reduces bundle size
PPR Static shell + dynamic content streaming Balances SEO and personalization
Turbopack Rust incremental builds 10x faster development server
use cache Declarative component-level caching Fine-grained caching control

(2) Why Choose Next.js

▶ Example: Creating and Running a Next.js 16 Project

Output:

TEXT
Diagram: Next.js 16; App Router File System Routing; Rendering Engine SSR/SSG/ISR/PPR; Data Collection Server Components; API Routes Route Handlers; Build Tools Turbopack.
BASH
# 1. Usage create-next-app Create a Project(Recommendations)
npx create-next-app@latest my-next-app --ts --tailwind --app

# 2. Go to the project directory
cd my-next-app

# 3. Start the development server(Turbopack Default)
npm run dev

# 4. Excerpt from terminal output
▲  ▲  ▲  ▲  ▲  ▲
 ▲  Next.js 16.2.10 (Turbopack)
 ▲  Local:        http://localhost:3000
 ▲  Environments: .env.local

Output:

TEXT
▲ Next.js 16.2.10
- Local: http://localhost:3000
✓ Ready in 876ms (Turbopack)

Output:

TEXT
The development server is running at http://localhost:3000. Open this URL in a browser to see the default Next.js welcome page.

▶ Example: What Can a Next.js Page Do?

TSX
// app/page.tsx — One page = Data Collection + Rendering + Interaction
export default async function HomePage() {
  const data = await fetch('https://jsonplaceholder.typicode.com/posts/1');

  return (
    <main>
      <h1 className="text-2xl font-bold">Welcome to Next.js 16</h1>
      <p>Server-rendered content: {data.title}</p>
    </main>
  );
}

Output:

TEXT
<h1>Welcome to Next.js 16</h1>
<p>Server-rendered content: sunt aut facere repellat provident</p>

Output:

TEXT
Browser renders: A heading "Welcome to Next.js 16" and server-rendered content from the API — the data was fetched on the server and delivered as pre-rendered HTML.


4. From the Pages Router to the App Router

(1) Historical Development

100%
timeline
    title Next.js Evolution of Routing Systems
    2016 : Next.js 1.0 Published Pages Router
    2019 : 9.3 Support SSG + getStaticProps
    2021 : 12 Published, React 18 + Rust Compiler
    2022 : 13 Published, App Router beta (RSC)
    2023 : 14 Stable App Router, Turbopack beta
    2025 : 15 Default App Router, React 19
    2026 : 16 Turbopack Default, PPR stable, use cache
Version Routing System Data Retrieval Method Rendering Mode
v1-v12 Pages Router getServerSideProps / getStaticProps SSR / SSG
v13-v14 Pages + App Router (optional) RSC + fetch SSR / SSG / ISR
v15 App Router (default) RSC + Server Actions SSR / SSG / ISR / PPR
v16 App Router (Exclusive) RSC + use cache SSR / SSG / ISR / PPR

(2) The Core Conceptual Model of the App Router

The key change in the App Router is that components are executed on the server by default.

TSX
// Pages Router Old Model (v12)
export async function getServerSideProps() {
  return { props: { data: await fetchData() } };
}
export default function Page({ data }) {
  return <div>{data}</div>; // All code is on the client side
}

// App Router New Model (v16)
export default async function Page() {
  const data = await fetchData(); // Retrieve it directly within the component
  return <div>{data}</div>; // Default Server Component
}

▶ Example: Code Comparison Between the Pages Router and the App Router

Output:

TEXT
Renders the Page component UI.
TSX
// ============================================
// Pages Router (pages/posts/[id].tsx)
// Requires additional export getServerSideProps
// ============================================
export async function getServerSideProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  return { props: { post: await res.json() } };
}
export default function PostPage({ post }) {
  return <h1>{post.title}</h1>;
}

// ============================================
// App Router (app/posts/[id]/page.tsx)
// Directly async component,No additional export required
// ============================================
export default async function PostPage({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.id}`);
  return <h1>{post.title}</h1>;
}

Output:

TEXT
Pages Router: 18 lines of code (including getServerSideProps)
App Router: 8 Run the code(Directly async component)
Savings 55% Sample Code

Output:

TEXT
The App Router reduces boilerplate by 55%: no getServerSideProps needed, direct async component, and automatic data fetching within the component body.


5. An Overview of New Features in Next.js 16

(1) Five Core Features

100%
graph LR
    A[Next.js 16] --> B[Turbopack Default<br/>Development and Build 10x Faster]
    A --> C[PPR Stable<br/>Partial Pre-rendering]
    A --> D[use cache<br/>Declarative Caching]
    A --> E[React 19<br/>Actions + use()]
    A --> F[Proxy API<br/>Replace part of middleware]
    A --> G[after()<br/>Post-Response Tasks]

    style A fill:#cce5ff
    style B fill:#d4edda
Feature Status Developer Benefits
Turbopack Default Stable Development builds are 10x faster, with instant HMR updates
Partial Prerendering Stable Static Shell SEO + Dynamic Content Personalization
use cache Stable Component-level caching, replaces getStaticProps
React 19 Built-in Server Actions, use(), useOptimistic
Proxy API New Server-side proxy forwarding, replacing some middleware
after() New Asynchronous tasks after a response (logging/analysis)

(2) Turbopack Default Build

Turbopack is an incremental bundling tool written in Rust by Vercel, and it is enabled by default in Next.js 16.

Comparison Item Webpack (v15) Turbopack (v16)
Cold Start 5–10 s 0.5–1 s
HMR Hot Reload 50–200 ms < 10 ms
Build Speed Baseline 10x Faster
Configuration Level Complex Zero Configuration

▶ Example: Turbopack Instant Hot-Update Experience

BASH
# Next.js 16 Start the development server,Use by default Turbopack
npm run dev

# Console Output
▲  ▲
▲  Next.js 16.2
▲  - Local: http://localhost:3000
▲  - Turbopack (experimental): ✓ loaded in 876ms

# Save after editing any file — Instant Hotfixes
✔ Updated /app/page.tsx in 3ms

Output:

TEXT
Turbopack Start Time: 876ms
Hotfix Release Time: 3ms
Comparison Webpack Cold Start: 5-10s

Output:

TEXT
Turbopack HMR: 4ms per file update (vs 50-200ms with Webpack). Cold start: 876ms (vs 5-10s). Large project builds: 10x faster overall.

(3) Partial Prerendering (PPR)

PPR is the most significant innovation in Next.js 16—it allows the static parts of a page to be pre-rendered as HTML, while the dynamic parts are streamed via Suspense boundaries.

100%
graph TB
    subgraph PPR Page
        A[Static Enclosure<br/>Pre-rendering HTML] --> B[Navigation Bar]
        A --> C[Sidebar]
        A --> D[Suspense Boundary<br/>---]
        D --> E[Dynamic Content<br/>Streaming Rendering]
        D --> F[User Data<br/>Streaming Rendering]
    end

    style A fill:#d4edda
    style D fill:#f8d7da
Rendering Strategy Build Time Request Time Caching SEO
SSR ✅ Full rendering
SSG ✅ Full pre-rendering
ISR ✅ Full pre-rendering ✅ On-demand regeneration
PPR ✅ Static shell ✅ Dynamic partial flow

(4) use cache Declarative Caching

TSX
// app/page.tsx — Usage use cache Instructions
import { unstable_cache as cache } from 'next/cache';

export default async function Page() {
  const data = await getData();
  return <div>{JSON.stringify(data)}</div>;
}

const getData = cache(
  async () => {
    return fetch('https://api.example.com/expensive-data');
  },
  ['expensive-data'],
  { revalidate: 3600 }
);

▶ Example: Practical Application of the PPR + Use Cache Combination

Output:

TEXT
Fetches data and renders the result.
TSX
// ============================================
// PPR Static shell + use cache Smart Caching
// Home = Static Header + Dynamic Content Recommendations (cached 1 hour)
// ============================================

// app/page.tsx
import { Suspense } from 'react';
import { RecommendedProducts } from './RecommendedProducts';

export default function HomePage() {
  return (
    <div>
      <header className="bg-gray-100 p-4">
        <h1>Welcome to ShopHub</h1>
        <nav>Categories | Deals | Support</nav>
      </header>

      {/* PPR Boundary:Dynamic Content Recommendations */}
      <Suspense fallback={<div className="animate-pulse h-40 bg-gray-200" />}>
        <RecommendedProducts />
      </Suspense>
    </div>
  );
}

Output:

TEXT
Renders a static shell immediately, with dynamic content loading inside Suspense boundaries.
Visible text: Welcome to ShopHub | Categories | Deals | Support
TSX
// app/RecommendedProducts.tsx
import { unstable_cache as cache } from 'next/cache';

const getProducts = cache(
  async () => {
    return fetch('https://fakestoreapi.com/products?limit=4');
  },
  ['recommended-products'],
  { revalidate: 3600 }
);

export async function RecommendedProducts() {
  const products = await getProducts();
  return (
    <div className="grid grid-cols-4 gap-4 p-4">
      {products.map(p => (
        <div key={p.id} className="border rounded p-2">
          <img src={p.image} alt={p.title} className="h-32" />
          <p className="font-bold">{p.title}</p>
          <p>${p.price}</p>
        </div>
      ))}
    </div>
  );
}

Output:

TEXT
When the page loads:
1. Static Header(Navigation Bar)Show Now
2. Recommended Area Display Skeleton Screen(Gray Placeholder Animation)
3. Once the data is ready,4 Streaming Rendering of Product Cards
4. The same user 1 Repeated visits within an hour are served from the cache,No need to restart fetch

(5) Deep Integration with React 19

Next.js 16 comes with React 19 built-in and supports:

▶ Example: React 19 Server Actions Quick Form

Output:

TEXT
The page renders as described above, with the UI updating based on the described behavior.
TSX
// ============================================
// Server Action:Form submission directly calls a backend function
// No need to create them manually API Route
// ============================================

// app/contact/page.tsx
export default function ContactPage() {
  async function handleSubmit(formData) {
    'use server';
    const name = formData.get('name');
    const email = formData.get('email');
    // Write directly to the database or send an email
    console.log(`New contact: ${name} <${email}>`);
    // Redirect to the success page
    redirect('/contact/success');
  }

  return (
    <form action={handleSubmit}>
      <input name="name" placeholder="Your name" required />
      <input name="email" type="email" placeholder="Your email" required />
      <button type="submit">Send</button>
    </form>
  );
}

Output:

TEXT
A form with input fields and a submit button.
On submit, the server action processes the data and redirects to a success page.

Output:

TEXT
After the form is submitted:
1. handleSubmit Functions are executed on the server
2. formData Automatically Collect Form Fields
3. redirect Execution Server 303 Redirect
4. No coding required API Route / fetch Code


6. Framework Comparison: Next.js vs Remix vs Nuxt vs Astro

(1) Four-Framework Positioning

100%
graph TB
    subgraph "Full-Stack Framework"
        A[Next.js<br/>React Ecology] --> B[Remix<br/>Web Standards First]
        C[Nuxt<br/>Vue Ecology]
    end
    subgraph "Static Site"
        D[Astro<br/>Multi-Frame Islands]
    end

    style A fill:#cce5ff
    style C fill:#d4edda

(2) Detailed Comparison

Dimension Next.js 16 Remix 2 Nuxt 4 Astro 5
Base Framework React 19 React 18 Vue 3 / Nitro Any (Islands)
Routing Type File System (App Router) File System File System File System
Rendering Mode SSR/SSG/ISR/PPR SSR/SSG SSR/SSG/ISR SSG (default) / SSR
PPR ✅ Stable
Server Components ✅ Default
use cache ✅ Stable
Turbopack ✅ Default Vite Vite
Build Speed 10x (Turbopack) 1x 1x 1x
Data Retrieval RSC + fetch loader + action asyncData No built-in
API Routes Route Handlers action + resource server routes None
Learning Curve Medium (Requires React) Medium (Requires Web Standards) Medium (Requires Vue) Low (Any)
Star 130k⭐ 30k⭐ 55k⭐ 50k⭐
Deployment Platform Vercel + Any Fly + Any Vercel + Any Netlify + Any

(3) Selection Recommendations

Scenario Recommended Framework Reason
Full-Stack SaaS Application Next.js 16 PPR + RSC + Server Actions: The Best
Content-focused websites/blogs Astro Zero JS output, ultimate performance
Web Standards First Remix Adheres to HTTP specifications and FormData
Vue Tech Stack Nuxt A Natural Extension of the Vue Ecosystem
E-commerce/Dashboard Next.js 16 PPR static shell + dynamic data isolation
Static Documentation Site Astro Islands architecture + native MDX support


7. Use Cases and Selection Recommendations

(1) Use Cases for Next.js 16

Scenario Description Typical Customers
SaaS Platform Dashboard + Multi-tenant + Real-time Data Notion, Linear
E-commerce Website Product Catalog (SSG) + Shopping Cart (SSR) TikTok Shop
Content Platform Articles (ISR) + Recommendations (Streaming) Medium
Admin Panel PPR Static Shell + Dynamic Widget Vercel Dashboard
AI Applications Streaming Text Generation + SSE Vercel AI SDK

(2) Situations Where It Is Not Appropriate



8. Complete Example: A Page Combining Multiple Rendering Strategies

TSX
// ============================================
// Comprehensive Example:E-commerce Product Detail Page
// Features:SSG Static Directory + PPR Recommendations + ISR Comments
// ============================================

// app/products/[id]/page.tsx
import { Suspense } from 'react';
import { notFound } from 'next/navigation';

// Static Page Parameter Generation(Pre-generate during build)
export async function generateStaticParams() {
  const products = await fetch('https://fakestoreapi.com/products');
  const ids = await products.json();
  return ids.map(p => ({ id: String(p.id) }));
}

export default async function ProductPage({ params }) {
  const product = await fetch(
    `https://fakestoreapi.com/products/${params.id}`
  );

  if (!product) {
    notFound();
  }

  return (
    <div className="container mx-auto p-4">
      {/* Static Section:Basic Product Information */}
      <div className="flex gap-8">
        <img src={product.image} alt={product.title} className="w-64 h-64" />
        <div>
          <h1 className="text-2xl font-bold">{product.title}</h1>
          <p className="text-xl text-green-600">${product.price}</p>
          <p className="mt-4">{product.description}</p>
        </div>
      </div>

      {/* PPR Dynamic Boundary:Recommended Products */}
      <Suspense fallback={<div>Loading recommendations...</div>}>
        <Recommendations category={product.category} />
      </Suspense>

      {/* ISR Comments Section:Regenerate every hour */}
      <Suspense fallback={<div>Loading reviews...</div>}>
        <Reviews productId={params.id} />
      </Suspense>
    </div>
  );
}

// app/products/[id]/Recommendations.tsx
async function Recommendations({ category }) {
  const products = await fetch(
    `https://fakestoreapi.com/products/category/${category}`
  );
  return (
    <div className="mt-8">
      <h2 className="text-xl font-bold">Recommended Products</h2>
      <div className="grid grid-cols-4 gap-4 mt-4">
        {products.slice(0, 4).map(p => (
          <div key={p.id} className="border p-2 rounded">{p.title}</div>
        ))}
      </div>
    </div>
  );
}

// app/products/[id]/Reviews.tsx
async function Reviews({ productId }) {
  const reviews = await fetch(
    `https://api.example.com/reviews/${productId}`,
    { next: { revalidate: 3600 } }
  );
  return (
    <div className="mt-8">
      <h2 className="text-xl font-bold">Customer Reviews</h2>
      {reviews.map(r => (
        <div key={r.id} className="border-b py-2">
          <p className="font-bold">{r.author}</p>
          <p>{r.content}</p>
        </div>
      ))}
    </div>
  );
}

Expected Output:

TEXT
1. Product Basic Information Displayed Instantly(SSG Static HTML)
2. Recommended Areas Display "Loading recommendations..." Placeholder
3. Comments Section Display "Loading reviews..." Placeholder
4. Streaming Rendering of Recommended Content(PPR)
5. Cached comment content 1 Update as needed after X hours(ISR)
6. The entire page is complete SEO Metadata

❓ FAQ

Q Does Next.js 16 require React 19?
A Yes, Next.js 16 includes React 19 by default, and all of React 19’s new features (Server Actions, use(), and useOptimistic) are available in Next.js. You don’t need to install React separately; npm create-next-app will automatically install the matching version.
Q Can the App Router and Pages Router be used together?
A Next.js 15 supports using them together, but Next.js 16 no longer recommends the Pages Router. If you have an older project, the official recommendation is to gradually migrate to the App Router. New projects should always use the App Router.
Q What is the difference between PPR and ISR?
A PPR (Partial Prerendering) is a hybrid approach at the page-section level—static parts are prerendered as HTML, while dynamic parts are loaded on the fly. ISR (Incremental Static Regeneration) operates at the page level—the entire page is statically generated and regenerated at regular intervals. Simply put: PPR = a mix of static and dynamic content within a single page; ISR = the entire page is updated at regular intervals.
Q How much faster is Turbopack than Webpack?
A According to official Next.js data, Turbopack is 10 times faster than Webpack during cold starts (876 ms vs. 8 s) and 50 times faster during hot reloads (3 ms vs. 150 ms). The difference is even greater in large projects.
Q Is Next.js suitable for building API backends?
A Yes, but it’s not recommended as the sole backend. Next.js’s route handlers are well-suited for the BFF (Backend for Frontend) layer; for complex business logic, it’s recommended to use a separate backend (such as Express or Fastify). Next.js focuses on the frontend and BFF.
Q Does Next.js 16 support self-hosting with Docker?
A Yes. Next.js 16’s output: 'standalone' mode can output a standalone directory, which, when combined with Docker’s multi-stage builds and an Nginx reverse proxy, enables self-hosted deployment.

📖 Summary


📝 Exercises

  1. Basic Question (⭐): Read the official Next.js 16 homepage (nextjs.org) and describe, in your own words, the three core principles of Next.js (50 characters or fewer).

  2. Advanced Exercise (⭐⭐): Use create-next-app to create a new project (npx create-next-app@latest my-app --ts --tailwind), start the development server, take a screenshot of the console output, and highlight the Turbopack startup time.

  3. Challenge (⭐⭐⭐): Choose a project you’ve previously built using a React SPA (or a product you’re familiar with) and analyze which parts should use SSG, which should use SSR, and which could use PPR if the project were rewritten using Next.js 16. Write a migration plan of no more than 200 characters.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏