DEV Community

Cover image for Next.js 15: New Features for High-Performance Development
Abdulnasır Olcan
Abdulnasır Olcan

Posted on

Next.js 15: New Features for High-Performance Development

Next.js 15 brings several advanced features and improvements that significantly enhance both performance and developer experience. Here’s a detailed breakdown of the key updates with examples:

1. Partial Pre-Rendering (PPR) with Detailed Use Case

Concept: PPR allows combining static (SSG) and dynamic (SSR) rendering in a single page. This is particularly useful in scenarios where you want to optimize performance for SEO while fetching dynamic content after the page loads.

Example: E-Commerce Product Page

Consider a product page that statically renders the basic product details like title and description, but fetches up-to-date prices dynamically from an API.

import { Suspense } from 'react';
import StaticProductDetails from '@/components/StaticProductDetails';
import DynamicPrice from '@/components/DynamicPrice';

export const experimental_ppr = true;  // Enabling Partial Pre-rendering

export default function ProductPage({ productId }) {
  return (
    <>
      <StaticProductDetails productId={productId} />  {/* Static */}
      <Suspense fallback={<div>Loading price...</div>}>
        <DynamicPrice productId={productId} />  {/* Dynamic */}
      </Suspense>
    </>
  );
}

Enter fullscreen mode Exit fullscreen mode

Here, the StaticProductDetails component is fetched at build time, so it loads instantly, whereas the DynamicPrice is fetched on the client side for the freshest data.

To enable PPR, the next.config.js should look like this:

const nextConfig = {
  experimental: {
    ppr: 'incremental',  // Enable partial pre-rendering incrementally
  },
};
module.exports = nextConfig;

Enter fullscreen mode Exit fullscreen mode

2. Enhanced Caching Mechanisms

Concept: In Next.js 15, fetch() no longer caches data by default, offering more fine-grained control over data freshness.

Example: API Fetch with Explicit Caching Strategy

Consider a news website where certain articles are frequently updated (breaking news), while others remain relatively static (editorials). You can explicitly define how each API fetch behaves using the new caching options.

// Fetch breaking news with no cache
const breakingNews = await fetch('https://...', {
  cache: 'no-store', // No caching, always fetch the latest
});

// Fetch editorials with caching for better performance
const editorials = await fetch('https://...', {
  cache: 'force-cache', // Cache for quick loading
});

Enter fullscreen mode Exit fullscreen mode

In this example, breaking news will always be up-to-date, while editorials are cached for faster loading times.

3. after() API for Post-Response Operations

Concept: The after() API allows executing tasks (like logging or analytics) after the client has received the response, optimizing perceived performance by deferring non-critical work.

Example: Logging User Actions After Response

Imagine you're running a blog where user visits are logged to track popular posts, but you don’t want this logging to delay the user’s page load.

import { unstable_after as after } from 'next/server';
import { logPageView } from '@/utils/logger';

export default function BlogPage({ content }) {
  after(() => {
    logPageView();  // Log page view after the response has been sent
  });

  return <div>{content}</div>;
}

Enter fullscreen mode Exit fullscreen mode

This example ensures that the user gets the page as quickly as possible, while the logging happens in the background after the page is loaded.

4. Turbopack for Fast Builds

Concept: Turbopack, the new build system for Next.js, written in Rust, significantly speeds up local development, reducing build times and improving developer productivity.

Example: Using Turbopack in Development

To enable Turbopack when starting a new project, simply run:

npx create-next-app --turbo

Enter fullscreen mode Exit fullscreen mode

To enable it for an existing project, add the following to your package.json:

{
  "scripts": {
    "dev": "next dev --turbo"
  }
}

Enter fullscreen mode Exit fullscreen mode

Turbopack greatly improves build times, especially for large-scale projects with many dependencies, making it a great tool for enterprise-level applications.

5. Improved Hydration Error Debugging

Concept: Hydration errors occur when the server-rendered HTML doesn’t match the React-generated HTML on the client. Next.js 15 makes it easier to debug by showing clearer error messages with exact discrepancies.

Example: Hydration Mismatch with State

Let's say your component incorrectly initializes state on the client:

function Counter() {
  const [count, setCount] = useState(0);  // State differs on the server
  useEffect(() => setCount(5), []);  // State set to 5 after component mounts

  return <p>{count}</p>;  // Mismatch during hydration
}

Enter fullscreen mode Exit fullscreen mode

In Next.js 15, the hydration error will clearly show the mismatch between the initial render (0) and the updated state (5), making it easier to trace and fix issues.

6. Advanced Integration with React 19

Concept: Next.js 15 requires React 19 and fully supports the new React Compiler, which automates component optimization, eliminating the need for hooks like useMemo or useCallback for performance.

Example: React 19’s useActionState

With React 19, you can leverage the new hooks like useActionState for managing actions within your components efficiently.

import { useActionState } from 'react';

function ActionComponent() {
  const [actionState, startAction] = useActionState(async () => {
    // some async operation
  });

  return (
    <div>
      <button onClick={startAction}>Start Action</button>
      {actionState.status === 'loading' && <p>Loading...</p>}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

This hook simplifies managing action states (e.g., loading, success, error) without needing to manually track these states with useState.

7. Improved Developer Experience with create-next-app

Concept: Next.js 15 revamps the create-next-app tool, offering an option to start with minimal boilerplate or use Turbopack for improved build times.

Example: Minimal Setup with --empty

You can now start with a clean slate, reducing setup time by creating an empty Next.js project:

npx create-next-app --empty

Enter fullscreen mode Exit fullscreen mode

This generates a basic "Hello World" project without unnecessary files, ideal for developers who want to start from scratch.

8. Step-by-Step Guide to Creating an Advanced Next.js 15 Project

Here’s a detailed guide on setting up and creating a Next.js 15 project with all the advanced features discussed earlier. We’ll cover the project creation and configuration.

1. Create a New Next.js 15 Project

First, let’s start by creating the project using create-next-app, which is the official starter kit for Next.js.

To install Next.js 15, run the following command in your terminal:

npx create-next-app@rc my-nextjs-project --turbo

Enter fullscreen mode Exit fullscreen mode

This command does the following:

--turbo enables Turbopack, the new Rust-based bundler, which speeds up builds and hot-reloading during local development.

Alternatively, if you want a minimal project setup (without boilerplate), use the --empty flag:

npx create-next-app@rc my-nextjs-project --empty

Enter fullscreen mode Exit fullscreen mode

This creates a clean Next.js app with just a "Hello World" page.

2. Set Up Your next.config.js with Advanced Features

After the project is set up, you can enable the experimental features discussed earlier by configuring your next.config.js file.

Here’s a full example of a next.config.js file with several advanced features enabled:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    ppr: 'incremental',  // Enable Partial Pre-rendering
    after: true,         // Enable after() API for post-response tasks
    reactCompiler: true, // Enable React 19 Compiler optimizations
  },
  images: {
    formats: ['image/avif', 'image/webp'],  // Optimize images with Next.js
  },
  future: {
    strictPostcssConfiguration: true, // Ensure strict CSS settings
  },
};

module.exports = nextConfig;

Enter fullscreen mode Exit fullscreen mode

3. Add Necessary Pages and Components

Create a basic structure for your project with the following components:

a. pages/index.js - Main page:

export default function Home() {
  return <h1>Welcome to Next.js 15</h1>;
}

Enter fullscreen mode Exit fullscreen mode

b. components/StaticComponent.js - Static component for PPR:

export default function StaticComponent() {
  return <div>Static content here</div>;
}
Enter fullscreen mode Exit fullscreen mode

c. components/DynamicComponent.js - Dynamic component fetched client-side:

import { Suspense } from 'react';

export default function DynamicComponent() {
  return <div>Dynamic content loaded!</div>;
}

Enter fullscreen mode Exit fullscreen mode

d. pages/product.js - PPR example page:

import { Suspense } from 'react';
import StaticComponent from '@/components/StaticComponent';
import DynamicComponent from '@/components/DynamicComponent';

export const experimental_ppr = true;

export default function ProductPage() {
  return (
    <>
      <StaticComponent />
      <Suspense fallback={<div>Loading dynamic content...</div>}>
        <DynamicComponent />
      </Suspense>
    </>
  );
}

Enter fullscreen mode Exit fullscreen mode

e. Testing the Setup

npm run dev

Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000 to see your project running. This includes Partial Pre-rendering, Turbopack, and more advanced optimizations.

Features Covered:

- Partial Pre-rendering (PPR)
- after() API for post-response operations
- Caching optimizations
- Turbopack integration for faster builds
- React 19 and Compiler optimizations

These examples cover a wide array of use cases, showing how you can leverage Next.js 15 to build faster, more optimized web applications while improving both the user and developer experience. From PPR for hybrid rendering, to using the after() API for deferred tasks, Next.js 15 introduces tools that significantly push the boundaries of modern web development​
Next.js by Vercel - The React Framework.

Reference: nextjs15

Top comments (0)