Next.js 13 brings a slew of new features, including the new Turbopack bundler, support for React Server Components, and more. Let's get started with Next.js 13.
Next.js is like React with benefits, in that it delivers all the features of React with ease-of-use conventions and a well-defined client-server stack. Next.js 13 is the newest version, released by Vercel at the Next.js conference in October 2022. It brings a slew of new features, including a bundler called Turbopack and support for several React-incubated optimizations like React Server Components and streaming rendering.
All told, Next.js 13 is a significant milestone, bringing together advancements in React and Next itself in a pleasantly usable developer experience package. This release also packs in considerable behind-the-scenes optimization. Let's take a tour of what's new in Next.js 13.
The new Turbopack bundler
Turbopack and Turborepo
In the Vercel universe, Turbopack is the sibling of Turborepo. Together, they make up the two cornerstones of Vercel’s systems-oriented efforts to evolve front-end tooling. Turbopack is the bundler and Turborepo is monorepo build tool.
Turbopack is written in Rust, which seems to be the go-to choice for systems-oriented tooling these days. Rust’s inherent speed is one reason underlying Turborepo’s performance as compared with other build tools. (Rust is something like C++, but with more memory safety.) Interestingly, the bundler space has been very active lately, with the Vite build tool gaining mindshare as the successor to Webpack. Vite is written in Go, a language of similar vintage to Rust. But Rust seems to have the edge on efficiency.
Turbopack also has architectural changes like clever use of caching, which improves the handling of source changes in an optimized way. The basic premise is that Turbopack holds a granular model of the changes that were already built and only builds those that are required to reflect ongoing changes.
The future of Turbopack
The new /app directory
Now let’s look at our directory layout, where you will notice the new /app directory. This is a new feature of Next.js 13. Basically, everything in the /app directory participates in the next generation of React and Next.js features.
The /app directory lives next to the familiar /pages directory and supports more advanced routing and layout capabilities. Routes that match in both /pages and /app will go to /app, so you can gradually supersede existing routes.
The basic routing in /app is similar to /pages in that the nested folders describe the URL path, so /app/foo/bar/page.js becomes localhost:3000/foo/bar in our dev setup.
Layouts in Next.js 13
One of the superpowers /app has over /pages is support for complex nested layouts. Every branch in your URL hierarchy can define a layout that is shared with its children (aka, leaf nodes). Moreover, the layouts preserve their state between transitions, avoiding the expense of re-rendering content in shared panels.
Each directory considers the page.tsx/jsx file as the content, and layout.tsx/jsx defines the template for both that page and the subdirectories. So, creating nested templates becomes simple. Moreover, the framework is smart enough to not re-render sections of the page that don’t change, so navigation will not repaint layouts that aren’t affected.
For example, let’s say we wanted to have a /foo/* directory where all the children are surrounded by a white border. We could drop a layout.tsx file into a /app/foo directory, something like Listing 5.
React Server Components
Sometimes, when using client-side hooks like useState or useEffect here (where the server can’t do the work beforehand), you need to tell React it's a client-side component. You do this by adding a ‘use client’ directive to the first line of the file. We've previously used filename extensions like .client.js and .server.js to designate a client component that uses client-side hooks, but now you must use the ‘use client’ directive at head of /app components.
Streaming render and suspense
Streaming is another newer React optimization enabled by the new concurrent render engine. It’s a fundamental change in how the React engine works. The basic idea is that the UI can be divided into sections, and sections that depend on data can define loading states while they load the data concurrently. Meanwhile, sections that do not depend on data can receive their content right away for immediate display.
You will primarily use this feature with the
Next.js 13’s /app directory means you by default can use streaming and
These benefits are especially pronounced when the network is slow or unreliable, for example with mobile. This new feature improves both user experience and developer experience. Developers will notice that data fetching is more consistent and standard. Adopting best practice is not only simpler, but is the default.
Better data fetching in Next.js 13
The Next.js data loading methods (getServerSideProps, getStaticProps, and getInitialProps) are now deprecated in favor of a newer approach to data fetching.
The first convention is to load data on the server, which has become simpler because all the components are server components by default. This eliminates the tendency to bounce data requests from the client off the server, when you really only need to directly hit the data store from the server and send the rendered UI to the client. See the Next.js documentation for a longer account of the reasoning behind preferring server-side data fetching.
Data fetching in the /app directory has to work with streaming and suspense. Components should make their own data requests, instead of parents passing in the data—even if that data is shared between components. The framework itself will avoid redundant requests, and it will ensure only the minimal requests are made and handed to the right components. The fetching API will also cache results for reuse.
All of this makes for a simpler architecture for data fetching that is still optimized. Developers can think less about data fetching performance and just grab data as it's needed, in the component that needs it.
The new approach means you can use the asynchronous Fetch API that we are familiar with directly in server components. (React and Next extend the API to handle deduping and caching.) You can also define async server components; for example, export default async function Page(). See the Next.js blog for more about the new fetch API.
The overall effect of all these improvements is a simpler application architecture that still benefits from behind-the-scenes performance optimization.
That’s quite a lot of action in Next.js 13—and there is more that I did not cover. Other new features include updates to the next/image component and a new font-loading system. Overall, Next.js 13 continues the tradition of delivering an all-in-one, React-with-benefits framework that makes it easier to take advantage of a variety of features.