Next.js 15 Exciting New Features Unveiled

Next.js, the beloved React framework, has just released its highly anticipated version 15, and it’s packed with exciting new features that are set to revolutionize the way we build web applications. In this blog post, we’ll dive into the most significant improvements and additions that Next.js 15 brings to the table.

Exciting news for Next.js developers! The Release Candidate (RC) for Next.js 15 is here. This means you can now get your hands on the newest features before the official stable release. It’s a great opportunity to try them out, see how they work in your projects, and provide feedback if needed.

Try the Next.js 15 RC today:

npm install next@rc react@rc react-dom@rc

React 19 RC

Next.js 15 RC leverages cutting-edge React features!

The Next.js App Router was built using React’s bleeding-edge “canary channel,” allowing developers to test and provide feedback on new React APIs even before the official v19 release. Now, the Next.js 15 Release Candidate offers support for React 19 RC, which introduces exciting features for both client-side and server-side development, including the new “Actions” functionality.

Want to dive deeper? Check out these resources:

React Compiler (Experimental)

Next.js 15 embraces a revolutionary tool: the React Compiler!

Developed by Meta’s React team, the React Compiler is an experimental powerhouse. It analyzes your code deeply, taking into account both standard JavaScript and the core principles of React (the “Rules of React“). This allows the compiler to automatically optimize your code, reducing the need for manual memorization techniques like useMemo and useCallback. This translates to simpler, easier-to-manage code with fewer errors.

The best part? Next.js 15 now fully supports the React Compiler, so you can leverage its benefits in your projects!

npm install babel-plugin-react-compiler

Then, add experimental.reactCompiler an option in next.config.js:

next.config.ts

const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

Optionally, you can configure the compiler to run in "opt-in" mode as follows:

next.config.ts

const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

Heads up! While Next.js 15 brings exciting support for the React Compiler, it’s currently only accessible through a Babel plugin. This plugin approach might lead to slightly slower build times compared to a fully integrated compiler.

Hydration error improvements

Next.js 15 steps up its error reporting game!

Building on the improvements in Next.js 14.1, version 15 introduces an enhanced hydration error view. Now, when a hydration error occurs, you’ll see the actual source code where the error originated, along with helpful suggestions on how to fix it.

Gone are the cryptic error messages of the past! Next.js 15 empowers you to pinpoint and resolve issues more efficiently.

(For reference, here’s an example of an older hydration error message from Next.js 14.1: )

Example of an older hydration error message from Next.js 14.1

Next.js 15 RC has improved this to:

Next.js 15

Caching updates

Next.js 15 refines how your apps handle caching!

Remember those “opinionated caching defaults” in the Next.js App Router? They aimed for peak performance out of the box, with the flexibility to customize when needed.

Thanks to your valuable feedback, we’ve taken a closer look at our caching logic and how it interacts with features like Partial Prerendering and third-party libraries using fetch.

What’s changing? In Next.js 15, the default behavior for caching has shifted. Now, fetch requests, GET Route Handlers, and the Client Router Cache will start uncached by default. Don’t worry, if you prefer the old behavior, you can still opt-in to caching.

We’re committed to continuous improvement in Next.js caching. Stay tuned for more details in the upcoming Next.js 15 general availability announcement!

fetch Requests are no longer cached by default

Next.js 15 updates how server-side data fetching handles caching!

Next.js uses a built-in cache to store data from previous requests. Previously (Next.js 14), by default, Next.js would try to use cached data first (force-cache) unless it involved dynamic functions or configurations.

fetch('https://...', { cache: 'force-cache' | 'no-store' });

What’s changed in Next.js 15? Now, the default behavior is to skip the cache entirely (no-store) for server-side data fetching (fetch requests) if you don’t specify a caching option. This means data will be retrieved from the server by default on every request.

Don’t worry, you can still control caching! Here’s how:

  • For a single request: Set the cache option to force-cache in your fetch call.
  • For a specific route: Set the dynamic route configuration option to 'force-static'.
  • For all requests in a Layout or Page: Set the fetchCache route configuration option to 'default-cache'. This will use force-cache for all fetch requests within that Layout or Page unless they have their own specific cache option defined.

Next.js 15 optimizes caching for GET route handlers!

In Next.js 14, GET requests for route handlers were automatically cached by default. However, Next.js 15 takes a different approach. Now, GET route handlers are not cached by default, offering more fine-grained control over caching behavior.

Still need caching? No problem! You can easily opt-in to caching by setting a static route configuration option like export dynamic = 'force-static'.

It’s important to note that special route handlers (like sitemap.ts, opengraph-image.tsx, and icon.tsx) and other metadata files remain static by default, just like in Next.js 14. This ensures these files are served efficiently without needing manual configuration.

Client Router Cache no longer caches Page components by default

Remember the experimental “staleTimes” flag from Next.js 14.2.0 for customizing the Router Cache? It’s still here in Next.js 15, but with a slight adjustment.

By default, Next.js 15 ensures you always see the freshest data on your screen as you navigate around your app. It achieves this by setting a “staleTime” of 0 for Page segments in the Router Cache. This means the client side will always fetch the latest data from the active Page components during navigation.

Don’t worry, some things haven’t changed:

  • Shared layout data: This data won’t be refetched unnecessarily, supporting partial rendering for efficiency.
  • Back/forward navigation: Your browser will still restore cached data for back and forward navigation, ensuring scroll position is maintained.
  • Loading.js: This file will remain cached for 5 minutes (or the value of your “staleTimes.static” configuration) to improve loading times.

If you prefer the previous Client Router Cache behavior from Next.js 14, you can still opt-in using a specific configuration (details provided below).

next.config.ts

const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
module.exports = nextConfig;

Incremental adoption of Partial Prerendering (Experimental)

Next.js 14 introduced Partial Prerendering (PPR), a performance booster that mixes static and dynamic content on the same page.

Imagine a webpage with static elements (like a navigation bar) and dynamic parts that change based on user input (like a search result list). Traditionally, Next.js would render the entire page as static unless you used special functions like cookies(), headers(), or made uncached data requests. These approaches made the whole page dynamic, slowing down the initial load.

PPR tackles this by letting you wrap dynamic UI elements in a “Suspense boundary.” When someone visits the page, Next.js instantly delivers a static HTML shell. Then, it renders and streams the dynamic parts within the same request, providing a smoother user experience.

To ease adoption, Next.js 15 offers an experimental option called experimental_ppr. This allows you to choose specific Layouts and Pages to benefit from PPR, enabling a gradual transition to this performance enhancement.

app/page.jsx

import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
	     <StaticComponent />
	     <Suspense fallback={...}>
		     <DynamicComponent />
	     </Suspense>
     </>
  };
}

To use the new option, you’ll need to set the experimental.ppr config in your next.config.js file to ‘incremental’:

next.config.ts

const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
};
 
module.exports = nextConfig;

Ready to unleash PPR’s power across your entire app?

Once you’ve enabled PPR (introduced Partial Prerendering) for all relevant segments of your app and feel confident, you can graduate from the experimental setting. Simply update the ppr value in your next.config.js file to true. This activates PPR for your entire application and any future routes you add.

We’ll share more details about our exciting PPR roadmap in the official Next.js 15 GA blog post. In the meantime, you can dive deeper into partial prerendering through the resources provided (link included).

Executing code after a response with next/after (Experimental)

While processing user requests, your server typically focuses on generating the response itself. But sometimes, you might also need to perform background tasks like logging, analytics, or updating other systems.

Here’s the challenge: these secondary tasks shouldn’t delay the user’s response. However, traditional serverless functions halt everything once the response is sent.

Introducing after(), a new experimental feature! This powerful API lets you schedule work to be processed after the user’s response has finished delivering. This way, your secondary tasks can run in the background without impacting the initial response time.

To use it, add experimental.after to next.config.js:

const nextConfig = {
  experimental: {
    after: true,
  },
};
 
module.exports = nextConfig;

Then, import the function in Server Components, Server Actions, Route Handlers, or Middleware.

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

Learn more about next/after

create-next-app updates

For Next.js 15, we’ve updated create-next-app with a new design.

When running create-next-app, there is a new prompt asking if you want to enable Turbopack for local development (defaults to No).

✔ Would you like to use Turbopack for next dev? … No / Yes

The --turbo flag can be used to enable Turbopack.

npx create-next-app@rc --turbo

Starting a brand new Next.js project just got even smoother. We’ve introduced a new --empty flag for the Next.js CLI. When you use this flag during project creation, it will skip generating any unnecessary files and styles. This results in a clean, minimal “hello world” page, the perfect starting point for your custom Next.js application.

npx create-next-app@rc --empty

Optimizing bundling of external packages (Stable)

External packages can significantly improve your app’s initial load time (cold start performance).

App Router:

  • By default, Next.js 15 automatically bundles external packages used in the App Router, for faster startup.
  • If you need to exclude specific packages, you can use the new serverExternalPackages configuration option.

Pages Router:

  • Unlike the App Router, the Pages Router doesn’t bundle external packages by default.
  • You can still choose to bundle specific packages using the existing transpilePackages option, but this requires manually listing each package.

Introducing a unified approach:

To simplify configuration across both routers, Next.js 15 introduces a new option: bundlePagesRouterDependencies. This option automatically bundles external packages used in the Pages Router, similar to the App Router’s default behavior.

You can then fine-tune this by using serverExternalPackages to exclude specific packages if needed, giving you more control over bundling behavior.

const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
module.exports = nextConfig;

Turbo Pack: High-Speed Bundling

Say hello to Turbo Pack, the new primary bundler in Next.js 15’s development mode. Turbo Pack is a highly organized and lightning-fast bundler that aims to speed up the development process. With Turbo Pack, you can expect faster builds, smoother development workflows, and improved support for bundling external packages in the app directory. It’s time to bid farewell to the limitations of Webpack and embrace the future of web development with Turbo Pack.

Vercel’s AI Code Generation

Vercel, the company behind Next.js, is pushing the boundaries of web development with its latest AI features. With AI streaming response, you can witness code being generated line by line in real time. While AI code generation is still in its early stages and primarily focused on basic HTML tasks, it’s an exciting glimpse into the future of web development. As AI continues to evolve, we can expect more sophisticated code-generation capabilities that will transform the way we build applications.

FAQ (Frequently Asked Questions)

When will Next.js 15 be generally available?

Next.js 15 is currently in the release candidate (RC) stage and is expected to move to general availability (GA) later this year, once React 19 is fully supported.

Can I start using Next.js 15 features right away?

While you can experiment with Next.js 15 features by running npx create-next-app@rc, it’s recommended to wait for the stable release before updating your production applications.

Will my existing Next.js projects break with the upgrade to version 15?

Next.js 15 aims to provide a smooth upgrade path for existing projects. However, it’s always a good practice to thoroughly test your application and review the migration guide before upgrading to ensure compatibility.

Next.js 15 is a significant milestone in the evolution of web development. With its powerful new features, improved performance, and enhanced developer experience, it empowers developers to build faster, more efficient, and user-friendly applications. Embrace the future of web development with Next.js 15 and unlock the full potential of your projects.

Leave a Comment