What’s New in Next.js 13 — and Why it Matters

In this post, we’ll give a brief intro to Next.js, and then break down some of the new features in Next.js 13 and discuss why they’re important.

The Next.js logo
The Next.js logo, credit: Next.js website

Last week, Vercel announced Next.js 13 at their developer conference.  The new release, currently in beta, introduces a ton of exciting new features and helps to tell a more powerful and cohesive story around server-side rendering for React, and how it ties together with interactive client-side components.

In this post, we’ll give a brief intro to Next.js, and then break down some of the new features in Next.js 13 and discuss why they’re important.

What is Next.js and Why Use It?

Next.js is a development framework which builds on React by enabling server-side rendering, additional server-side functionality and an improved devleopment and deployment toolchain.

The biggest benefits of server-side rendering with Next.js are in performance and SEO: by rendering on the server, the fully-rendered initial state of an application can be served up on a single request.  This means less work for the browser to do, and it also means that the content can be easily indexed by a search engine.  It also means rendered data can be cached (in part of in whole) to improve performance even further.

These Next.js features, among others, help to build on React's strong foundation and make up for some of the shortcomings of a purely client-side approach.  For any app where performance and SEO matter, Next.js is a welcome addition to the stack.  So with the background on Next.js, let's dig into what's coming in the upcoming Next.js 13 release.

app/ Directory for File-Based Routing

One of the greatest features of Next.js is file-based routing. Instead of dealing with gnarly route configuration in a tool like react-router, routes can be specified using the structure of your project directory. Simply place an entrypoint in the pages directory, and you’ve created a new route.

Next.js 13 builds on this concept and provides redesigned file routing with the new app/ directory. The app directory (which is optional) introduces a new layout structure with several new features and enhancements.

With the new routing scheme, the directory structure is changed somewhat. In Next.js 13, each path in the route now gets a dedicated directory with a page.js containing the entrypoint for the content. This table shows how basic routing is different in Next.js 12 and 13:

# Route         Next.js 12              Next.js 13
/               pages/index.js          app/page.js
/blog           pages/blog.js           app/blog/page.js
/blog/new       pages/blog/new.js       app/blog/new/page.js

In addition to the page.js for a route, the new structure lets us include several other special files in each path directory, including: layout.js, a layout component for the path (and all sub-paths); loading.js, a component for an instant loading state using React.Suspense under the hood; and error.js, a component rendered when the main component fails to load.

Because each path is now its own directory, we can also colocate source files inside of our path directories. We can include other components, as well as styles, tests, etc:

app/blog/page.js
app/blog/Header.js
app/blog/Header.css
app/blog/Header.test.js

File-based routing has always been a great feature, and the new app/ directory takes it to the next level. It simplifies development, and (perhaps on a nostalgic note), helps bring back the utter simplicity of building more static sites: the content paths match the content directory structure . Once again, use of the new app/ directory if fully optional, so you don’t have to migrate to the new structure right away.

React Server Components

The next exciting change in Next.js 13 is the addition of support for React server components. Server components let us execute and render React components on the server-side for faster delivery, smaller JavaScript bundle, and lower client-side rendering cost.

Additionally, depending on what kind of data is required to render a route, server components can be automatically cached either at build-time or at runtime for additional performance benefits.

The capabilities of server and client components do vary somewhat, so you will need to architect your application accordingly. The following table, taken from the documentation, outlines what capabilities the two different kinds of components have and what they are best used for.

Table comparing server and client component, taken from the Next.js documentation.

Server & client components can be mixed, meaning you can use server components for the fast-loading, non-interactive parts of your application, but leverage client components where needed for interactivity, browser APIs, etc.

When building out client components in your Next.js app, you’ll use the 'use client'; directive at the top of the file to mark it accordingly. Note that if you’re using third-party packages, you may need to create a client wrapper for those components.

Async Components & Data Fetching

Next.js 13 also introduces a new approach to fetching data for server-rendered components: async components. With async components, we can render components using Promises with async & await. If we need to fetch data from an external service or other API returning a Promise, we declare the component as async and simply await the result:

async function getData() {
  const res = await fetch('https://api.example.com/...');
  return res.json();
}

export default async function Page() {  
  const name = await getData();  
  return '...';
}

Previous versions of Next.js used an entirely different API to resolve the request data outside of the lifecycle of the component, which then is used as component props. This example shows a Next.js 12 approach to loading data from an external service:

// This gets called on every requestexport async function getServerSideProps() {  
  // Fetch data from external API  
  const res = await fetch(`https://.../data`)  
  const data = await res.json()  
  // Pass data to the page via props  
  return { props: { data } }
}

The older approach is still supported but not inside of the new app/ directory. If you want to take advantage of the new app/ directory structure and all of its cool new features, you’ll need to update your server components. If you’re not ready to, however, you can still use the Next.js 12  pages/ routing for your app.

Also note that async rendering and Promise support is not yet available for client components — but it is on the way via a proposed new use() hook:

All About React’s Proposed New use() Hook
First-class support for Promises is coming to React — here’s the proposal on how it’s expected to work

In the meantime, however, client-side components can use more traditional async methods, such as React.Suspensealongside lifecycle hooks like useEffect(), or using a 3rd-party library which enables such functionality.

Turbopack for lightning fast bundling

The last major change introduced with Next.js 13 is a new JavaScript bundler, Turbopack, billed as the “successor to Webpack”. Webpack, one of the most ubiquitous JavaScript build tools, is insanely configurable and powerful but can also be quite slow and clunky.

You Don’t Need Webpack — 3 Better Alternatives for Building Your JavaScript
A new generation of JavaScript bundlers offers greatly improved developer experiences

Turbopack is authored by the creators of Webpack, but is built with Rust and promises to be 700x faster than the original Webpack (and 10x faster than Vite, a more modern alternative). For a full breakdown of the similarities and differences, check out the Webpack & Turbopack comparison.

Be aware that Turbopack is currently in alpha and is not yet ready for production usage, but it’s definitely in good enough shape for a test-drive in development. Also note that Turbopack currently lacks a public plugin API (which is one of Webpack’s biggest strengths), but this will be addressed in the future.

If you create a new Next.js 13 app, you can try out the new Turbopack bundler using next dev --turbo to start your dev server.

Other Improvements

Though we focused on some of the big ticket items in this post, there are a number of other important features included in Next.js 13:

  • Better image loading support & performance with next/image
  • Improved font performance with next/font
  • Link API improvements with next/link

For a full list of changes, have a look at the Next.js 13 Blog Post from Vercel.

Recap — Server-Side React is Growing Up

In this post, we covered a number of new features in Next.js 13. While the new features described here touch on a variety of different areas, the overall theme to me is a maturing of the framework. Next.js 13, along with upcoming changes in React itself are beginning to tell a solid, coherent story around mixing React on the server and the client.

If you haven’t yet looked at Next.js or server-side React, now is a great time to check it out!