Skip to content
Back to Blog

Thursday, April 11th 2024

Next.js 14.2

Posted by

Next.js 14.2 includes development, production, and caching improvements.

Upgrade today or get started with:

Terminal
npx create-next-app@latest

Turbopack for Development (Release Candidate)

Over the past few months, we’ve been working on improving local development performance with Turbopack. In version 14.2, the Turbopack Release Candidate is now available for local development:

  • 99.8% of integrations tests are now passing.
  • We’ve verified the top 300 npm packages used in Next.js applications can compile with Turbopack.
  • All Next.js examples work with Turbopack.
  • We’ve integrated Lightning CSS, a fast CSS bundler and minifier, written in Rust.

We’ve been extensively dogfooding Turbopack with Vercel’s applications. For example, with vercel.com, a large Next.js app, we've seen:

  • Up to 76.7% faster local server startup.
  • Up to 96.3% faster code updates with Fast Refresh.
  • Up to 45.8% faster initial route compile without caching (Turbopack does not have disk caching yet).

Turbopack continues to be opt-in and you can try it out with:

Terminal
next dev --turbo

We will now be focusing on improving memory usage, implementing persistent caching, and next build --turbo.

  • Memory Usage - We’ve built low-level tools for investigating memory usage. You can now generate traces that include both performance metrics and broad memory usage information. These traces allows us to investigate performance and memory usage without needing access to your application’s source code.
  • Persistent Caching - We’re also exploring the best architecture options, and we’re expecting to share more details in a future release.
  • next build - While Turbopack is not available for builds yet, 74.7% of tests are already passing. You can follow the progress at areweturboyet.com/build.

To see a list of supported and unsupported features in Turbopack, please refer to our documentation.

Build and Production Improvements

In addition to bundling improvements with Turbopack, we’ve worked to improve overall build and production performance for all Next.js applications (both Pages and App Router).

Tree-shaking

We identified an optimization for the boundary between Server and Client Components that allows for tree-shaking unused exports. For example, importing a single Icon component from a file that has "use client" no longer includes all the other icons from that package. This can largely reduce the production JavaScript bundle size.

Testing this optimization on a popular library like react-aria-components reduced the final bundle size by -51.3%.

Note: This optimization does not currently work with barrel files. In the meantime, you can use the optimizePackageImports config option:

next.config.ts
module.exports = {
  experimental: {
    optimizePackageImports: ['package-name'],
  },
};

Build Memory Usage

For extremely large-scale Next.js applications, we noticed out-of-memory crashes (OOMs) during production builds. After investigating user reports and reproductions, we identified the root issue was over-bundling and minification (Next.js created fewer, larger JavaScript files with duplication). We’ve refactored the bundling logic and optimized the compiler for these cases.

Our early tests show that on a minimal Next.js app, memory usage and cache file size decreased from 2.2GB to under 190MB on average.

To make it easier to debug memory performance, we’ve introduced a --experimental-debug-memory-usage flag to next build. Learn more in our documentation.

CSS

We updated how CSS is optimized during production Next.js builds by chunking CSS to avoid conflicting styles when you navigate between pages.

The order and merging of CSS chunks are now defined by the import order. For example, base-button.module.css will be ordered before page.module.css:

base-button.tsx
import styles from './base-button.module.css';
 
export function BaseButton() {
  return <button className={styles.primary} />;
}
page.tsx
import { BaseButton } from './base-button';
import styles from './page.module.css';
 
export function Page() {
  return <BaseButton className={styles.primary} />;
}

To maintain the correct CSS order, we recommend:

  • Using CSS Modules over global styles.
  • Only import a CSS Module in a single JS/TS file.
  • If using global class names, import the global styles in the same JS/TS too.

We don’t expect this change to negatively impact the majority of applications. However, if you see any unexpected styles when upgrading, please review your CSS import order as per the recommendations in our documentation.

Caching Improvements

Caching is a critical part of building fast and reliable web applications. When performing mutations, both users and developers expect the cache to be updated to reflect the latest changes. We've been exploring how to improve the Next.js caching experience in the App Router.

staleTimes (Experimental)

The Client-side Router Cache is a caching layer designed to provide a fast navigation experience by caching visited and prefetched routes on the client.

Based on community feedback, we’ve added an experimental staleTimes option to allow the client-side router cache invalidation period to be configured.

By default, prefetched routes (using the <Link> component without the prefetch prop) will be cached for 30 seconds, and if the prefetch prop is set to true, 5 minutes. You can overwrite these default values by defining custom revalidation times in next.config.js:

next.config.ts
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
      static: 180,
    },
  },
};
 
module.exports = nextConfig;

staleTimes aims to improve the current experience of users who want more control over caching heuristics, but it is not intended to be the complete solution. In upcoming releases, we will focus on improving the overall caching semantics and providing more flexible solutions.

Learn more about staleTimes in our documentation.

Parallel and Intercepting Routes

We are continuing to iterate on on Parallel and Intercepting Routes, now improving the integration with the Client-side Router Cache.

  • Parallel and Intercepting routes that invoke Server Actions with revalidatePath or revalidateTag will revalidate the cache and refresh the visible slots while maintaining the user’s current view.
  • Similarly, calling router.refresh now correctly refreshes visible slots, maintaining the current view.

Errors DX Improvements

In version 14.1, we started working on improving the readability of error messages and stack traces when running next dev. This work has continued into 14.2 to now include better error messages, overlay design improvements for both App Router and Pages Router, light and dark mode support, and clearer dev and build logs.

For example, React Hydration errors are a common source of confusion in our community. While we made improvements to help users pinpoint the source of hydration mismatches (see below), we're working with the React team to improve the underlying error messages and show the file name where the error occurred.

Before:

An example of the Next.js error overlay before version 14.2.
An example of the Next.js error overlay before version 14.2.

After:

An example of the Next.js error overlay after version 14.2.
An example of the Next.js error overlay after version 14.2.

React 19

In February, the React team announced the upcoming release of React 19. To prepare for React 19, we're working on integrating the latest features and improvements into Next.js, and plan on releasing a major version to orchestrate these changes.

New features like Actions and their related hooks, which have been available within Next.js from the React canary channel, will now all be available for all React applications (including client-only applications). We're excited to see wider adoption of these features in the React ecosystem.

Other Improvements

  • [Docs] New documentation on Video Optimization (PR).
  • [Docs] New documentation on instrumentation.ts (PR)
  • [Feature] New overrideSrc prop for next/image (PR).
  • [Feature] New revalidateReason argument to getStaticProps (PR).
  • [Improvement] Refactored streaming logic, reducing the time to stream pages in production (PR).
  • [Improvement] Support for nested Server Actions (PR).
  • [Improvement] Support for localization in generated Sitemaps (PR).
  • [Improvement] Visual improvements to dev and build logs (PR)
  • [Improvement] Skew protection is stable on Vercel (Docs).
  • [Improvement] Make useSelectedLayoutSegment compatible with the Pages Router (PR).
  • [Improvement] Skip metadataBase warnings when absolute URLs don’t need to be resolved (PR).
  • [Improvement] Fix Server Actions not submitting without JavaScript enabled when deployed to Vercel (PR)
  • [Improvement] Fix error about a Server Action not being found in the actions manifest if triggered after navigating away from referring page, or if used inside of an inactive parallel route segment (PR)
  • [Improvement] Fix CSS imports in components loaded by next/dynamic (PR).
  • [Improvement] Warn when animated image is missing unoptimized prop (PR).
  • [Improvement] Show an error message if images.loaderFile doesn't export a default function (PR)

Community

Next.js now has over 1 million monthly active developers. We're grateful for the community's support and contributions. Join the conversation on GitHub DiscussionsReddit, and Discord.

Contributors

Next.js is the result of the combined work of over 3,000 individual developers, industry partners like Google and Meta, and our core team at Vercel. This release was brought to you by:

Huge thanks to @taishikato, @JesseKoldewijn, @Evavic44, @feugy, @liamlaverty, @dvoytenko, @SukkaW, @wbinnssmith, @rishabhpoddar, @better-salmon, @ziyafenn, @A7med3bdulBaset, @jasonuc, @yossydev, @Prachi-meon, @InfiniteCodeMonkeys, @ForsakenHarmony, @miketimmerman, @kwonoj, @williamli, @gnoff, @jsteele-stripe, @chungweileong94, @WITS, @sogoagain, @junioryono, @eisafaqiri, @yannbolliger, @aramikuto, @rocketman-21, @kenji-webdev, @michaelpeterswa, @Dannymx, @vpaflah, @zeevo, @chrisweb, @stefangeneralao, @tknickman, @Kikobeats, @ubinatus, @code-haseeb, @hmmChase, @byhow, @DanielRivers, @wojtekmaj, @paramoshkinandrew, @OMikkel, @theitaliandev, @oliviertassinari, @Ishaan2053, @Sandeep-Mani, @alyahmedaly, @Lezzio, @devjiwonchoi, @juliusmarminge, @szmazhr, @eddiejaoude, @itz-Me-Pj, @AndersDJohnson, @gentamura, @tills13, @dijonmusters, @SaiGanesh21, @vordgi, @ryota-murakami, @tszhong0411, @officialrajdeepsingh, @alexpuertasr, @AkifumiSato, @Jonas-PFX, @icyJoseph, @florian-lp, @pbzona, @erfanium, @remcohaszing, @bernardobelchior, @willashe, @kevinmitch14, @smakosh, @mnjongerius, @asobirov, @theoholl, @suu3, @ArianHamdi, @adrianha, @Sina-Abf, @kuzeykose, @meenie, @nphmuller, @javivelasco, @belgattitude, @Svetoslav99, @johnslemmer, @colbyfayock, @mehranmf31, @m-nakamura145, @ryo8000, @aryaemami59, @bestlyg, @jinsoul75, @petrovmiroslav, @nattui, @zhuyedev, @dongwonnn, @nhducit, @flotwig, @Schmavery, @abhinaypandey02, @rvetere, @coffeecupjapan, @cjimmy, @Soheiljafarnejad, @jantimon, @zengspr, @wesbos, @neomad1337, @MaxLeiter, and @devr77 for helping!