In this blog, we will explore the Next.js 15 RC to test the latest features for the upcoming stable release of Next.js. The first release candidate for Next.js 15 RC was rolled out on May 23, 2024. This means we can examine all the new development, production, and caching features.
The latest updates include several key features organized into stable and experimental improvements.
Next.js is a versatile, open-source React framework developed by Vercel. It is designed to easily build fast, SEO-friendly, and user-friendly web apps. It elegantly combines server-side rendering, static site generation, and client-side rendering capabilities, making it an outstanding choice for modern web development.
Its features include automatic code splitting, efficient routing, API routes, and an optimized production build, contributing to its performance and scalability. Moreover, Next.js prioritizes developer experience, offering fast refresh for a more seamless coding process. This ensures that it caters to the end user's needs and those creating the apps.
To upgrade to the latest version of Next.js (version 15 RC), use the following command with your preferred package manager:
npm i next@rc react@rc react-dom@rc eslint-config-next@rc
yarn add next@rc react@rc react-dom@rc eslint-config-next@rc
Please note that the minimum required versions for react and react-dom are 19. For more information on version upgrading, refer to the official documentation.
Before upgrading to React 19 RC, please check the new features and updates by visiting our blog.
With the unveiling of React 19 RC, the Next.js App Router is being developed on the React canary channel specifically for frameworks. This allows developers to utilize and provide input on the latest React APIs ahead of the official v19 launch. Next.js 15 RC will be compatible with React 19 RC, bringing forth novel features for both client-side and server-side environments, including Actions.
For more information, please refer to the React 19 upgrade guide.
The React Compiler is a new experimental compiler developed by the React team at Meta. It leverages its understanding of plain JavaScript semantics and the Rules of React to analyze and optimize your code. This deep understanding enables the compiler to automatically apply optimizations, reducing the need for manual memoization techniques like useMemo
and useCallback
. As a result, your code becomes more concise, easier to maintain, and less prone to errors.
With Next.js 15, React Compiler support has been added. However, the React Compiler can currently only be used in Next.js through a Babel plugin.
npm install babel-plugin-react-compiler
Add the experimental.reactCompiler
option in the next.config.js
file.
const nextConfig = {
experimental: {
reactCompiler: true,
},
};
module.exports = nextConfig;
Using the experimental option ensures support for the React Compiler in the following areas: App Router, Pages Router, Webpack, and Turbopack.
Note: The React Compiler is currently in an experimental phase, and its features and capabilities may evolve. It’s recommended that you stay updated with the latest developments and consider using it cautiously in your projects.
Next.js 15 has improved the way hydration errors are displayed. Hydration errors happen in Next .js when there is a mismatch between the HTML rendered on the server and the HTML rendered in the client during the initial load. This mismatch can be caused by text, incorrect HTML nesting, and browser-specific code. With the new improvements, when a hydration error occurs, the source code of the error is displayed, along with suggestions on how to fix the issue.
For more details, refer to the official Next.js documentation on Hydration error improvements.
Caching in Next.js is essential for improving performance and reducing server load. The Next.js App Router was introduced with opinionated caching defaults, designed to provide optimal performance by default with the ability to opt out when necessary.
In Next.js 15, the default behavior for caching fetch requests, GET Route Handlers, and the Client Router Cache has been updated. Previously, these were cached by default, but now they are uncached by default. If you prefer the old behavior, you can still opt into caching. Note that layouts and loading states will continue to be cached and reused during navigation.
An experimental staleTimes
flag was introduced to allow custom configuration of the Router Cache in Next.js 14.2.0. This flag still remains accessible in Next.js 15. However, we are changing the default behavior to a staleTime
of 0 for Page segments. This means that as you navigate your app, the client will always reflect the latest data from the Page component(s) that become active as part of the navigation. However, there are still important behaviors that remain unchanged:
Loading.js
is cached for 5 minutes or per staleTimes.static
config.You can opt into the previous client router cache behavior by setting the following configuration:
const nextConfig = {
experimental: {
staleTimes: { dynamic: 30 },
},
};
module.exports = nextConfig;
Let’s discuss the improvements in create-next-app
. When you launch the app, it now has a new landing page and provides a prompt for choosing Turbopack when creating the Next app.
The Next.js 14 release introduced an incremental bundler called Turbopack, which is written in Rust and designed to optimize JavaScript and TypeScript. It has been integrated into Next.js to improve development performance.
In the Next.js 15 RC, when running the create-next-app
command, a new prompt asks whether you would like to enable Turbopack for local development. The default setting is No.
✔ Would you like to use Turbopack for next dev? … No / Yes
The –turbo
flag can be used to activate Turbopack.
npx create-next-app@rc –turbo
To simplify the process of getting started on a new project, a new –empty
flag has been included in the CLI. This flag removes unnecessary files and styles, resulting in a minimal Hello world page.
npx create-next-app@rc –empty
Integrating external libraries can enhance an app’s initial load performance. By default, the App Router bundles external libraries, but you can exclude particular libraries using the serverExternalPackages
configuration option.
In the Pages Router, external libraries are not bundled by default. However, you can specify a list of libraries you wish to bundle through the transpilePackages
option, which requires individual package specifications.
To streamline configurations across both the App and Pages routers, a new option named bundlePagesRouterDependencies
was introduced. This setting will align with the App Router’s default behavior of automatically bundling external libraries. The serverExternalPackages
option remains available to exclude specific libraries as needed.
When handling a user request, the server usually focuses on tasks directly related to generating the response. However, additional tasks like logging, analytics, or synchronizing with external systems often need to be performed.
These secondary tasks should ensure the user’s response is timely. Deferring such tasks can be challenging because serverless functions typically stop execution as soon as the response is sent.
The after()
API, currently experimental, addresses this issue by allowing you to schedule tasks to run after the response has been streamed. This enables secondary tasks to execute without blocking the primary response.
To enable this feature, add experimental.after
to your 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';
export default function Layout({ children }) {
// Secondary task.
after(() => {
....
});
// Primary task.
return <>{children}</>;
} ;
Partial Prerendering, or PPR, was rolled out in Next.js 14. It is an optimization that blends static and dynamic rendering on the same page.
By default, Next.js uses static rendering unless dynamic functions like cookies()
, headers()
, or uncached data requests are used, which switch the entire route to dynamic rendering. With PPR, you can wrap dynamic UI components in a Suspense
boundary. When a new request is made, Next.js immediately serves a static HTML shell and then renders and streams the dynamic parts within the same HTTP request.
To facilitate incremental adoption, we've added an experimental_ppr
route config option to enable PPR for specific Layouts and Pages. Refer to the following code example.
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 this new option, set the experimental.ppr
config to incremental
in your next.config.js
file.
const nextConfig = {
experimental: {
ppr: 'incremental',
},
};
module.exports = nextConfig;
Once all segments have PPR enabled, setting the ppr
value to true
will be safe, enabling it for the entire app and all future routes.