Next.js 13.4 is finally here and it’s awesome!

Ryan C. Collins
Frontend Weekly
Published in
8 min readMay 9

--

This past week, the Vercel team posted a major announcement on their blog about the release of Next.js 13.4. To provide more context about why this is such an important release, we need to understand how the Vercel team handles releases to the public. Next.js 13 introduced new many new features, but most of them have remained in alpha & beta, even though they were included in the major release.

So despite the fact that Next.js dropped some major new upgrades in Version 13 last October, the features have not quite been ready for prime time. That changes in next.js 13.4! The new 13.4 release finally provides a stable release of one of the most important new features: the App Router.

In this article, we’ll dive into some of the features and improvements that come with this release. From the first stable release of the new app directory and app router to the latest advancements in Turbopack, there’s a lot to be excited about! Let’s get started.

Next.js 13.4: The new App Router

As mentioned, Next.js 13.4 is the first release that takes the new app directory and app router features out of beta!

As someone who has been playing with these features in sample projects, I can tell you that I’ve been getting antsy waiting to use them in production because they make the development experience in Next that much better.

Also, perhaps symbolic of the importance of this release, the Next.js documentation site had a major update to make the App Router the default! You can now toggle the docs between the new App Router and the previous Pages Router.

Below we’ll do a quick recap of the App Router by diving into some of the main features.

Routing in the App Directory

Routing in the new app directory is as simple as adding a page.tsx file that exports a React function component. The routing of the application is defined by the hierarchy of your folders within the app directory. For example, creating a page at the / route is as easy as adding a page.tsx file at the root of the app directory:

.
└── app/
└── page.tsx
// app/page.tsx
export default function Page() {
return <SomeJsx />
}

Next, let’s show how we can create more complex application routes using the new app router:

.
└── app/
├── page.tsx
├── about/
│ ├── page.tsx
│ └── layout.tsx
└── articles/
└── article/
└── [id]/
├── page.tsx
├── layout.tsx
└── components/
├── BlogArticle.tsx
└── Author.tsx

As you can see above, we are able to create a simple route such as /about , as well as create more complex routes like /articles/article/12345 using Next.js’ dynamic routes.

With the new App Router, our pages can make use of React Server Components, which allow us to simplify data fetching using the familiar async / await syntax.

// app/page.tsx
export default async function Page() {
const res = await fetch('https://api.example.com/...');
const data = res.json();
return '...';
}

In Next.js 13, files are server components by default. You can opt into client components by including the 'use client' directive at the top of your module.

'use client'
export default function ClientComponent({ id }: ArticleProps) {
useEffect(() => { //... }, [])
return //...
}

Also notice in our example file tree above, we added /components to our blog article folder. This was difficult in previous versions of Next.js because all files within the page directory were considered pages. Next.js 13 makes this a nicer experience by enforcing special file names for layout, page, template, etc.

Route segment configuration

Our pages can also export route segments that allow us to control how the pages render. One common practice in Next.js is to statically generate pages. We run into an issue when we use dynamic params though, how would Next.js know what pages to statically generate? We can make use of generateStaticParams to solve this.

In the example below, we export an async function called generateStaticParams that loads all of our blog articles and returns an array of objects with a property that matches the name of our dynamic route segment, in this case id . Next.js will use this to statically generate pages for each of our blog articles.

// app/articles/article/[id]/page.tsx
type ArticleProps = Pick<Article, 'id'>

export default async function Page({ id }: ArticleProps) {
const article = await(await fetchArticleById(id)).json();
return <BlogArticle article={article} />
}

export async function generateStaticParams(): ArticleProps[] {
const articles = await(await fetchArticles()).json();
return articles.map(article => ({ id: article.id }))
}

Next.js 13 gives us several route segment configuration options to control how Next.js renders the page. Aside from generateStaticParams, the most commonly used route segment configuration that I’ve been using is revalidate. When combined with static site generation (SSG), revalidate allows you to control how often the page will get regenerated.

Building on our previous example, we can set revalidate to 60 (seconds) to rebuild the page every 60 seconds. Note that it’s a bit more nuanced than that, so make sure to read up on ISR on the Next.js documentation site and let me know in the comments if you want me to write a separate article on ISR!

// app/articles/article/page.tsx
type ArticleProps = Pick<Article, 'id'>

export default async function Page({ id }: ArticleProps) {
const article = await(await fetchArticleById(id)).json();
return <BlogArticle article={article} />
}

export async function generateStaticParams(): ArticleProps[] {
const articles = await(await fetchArticles()).json();
return articles.map(article => ({ id: article.id }))
}

export const revalidate = 60

We can also tell next.js not to render pages for IDs that are not returned in generateStaticParams by making use of the dynamicParams route segment configuration:

export dynamicParams = false

Finally, we can force the page to generate statically or dynamically, depending on our use case. For example, if we have a page that is making use of query params, we may want it to be dynamically server rendered when the page is requested using the dynamic route segment:

export dynamic = 'force-dynamic'
// or: 'auto' | 'force-dynamic' | 'error' | 'force-static'

Layouts and Templates

Along with pages, Next.js 13 also introduced special files for layouts and templates. In the example above, you may have noticed that we included several layout.tsx files at various levels of the folder hierarchy. We created a root level layout.tsx, which is a typical practice in Next.js 13.

Within the root layout, we can create the html document, add scripts and other content to the head, provide semantic structure and wrap the app in providers. We no longer have to make use of the special <Head> and <Script> components from previous versions of Next. We can also add metadata here, but Next.js 13.2 introduced a new dynamic Metadata API for this that we’ll cover in another article.

Note that layouts and pages should typically be server components, so you should avoid forcing them to be client components by adding hooks or other client-only functionality.

// app/layout.tsx
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<script>//...</script>
</head>
<body>
<main>
<AppProvider>{children}</AppProvider>
</main>
</body>
</html>
);
}

// app/page.tsx
export default function Page() {
return //...;
}

Layout files can be added at each level of the app directory’s hierarchy to apply more specific layouts to different parts of the application. For example, let’s say we want to add a specific AppWrapper surrounding our blog articles. We can add a new layout.tsx file to the /app/articles/article/[id] directory next to the page.tsx file.

// app/articles/article/[id]/layout.tsx
export default function RootLayout({ children }) {
return (
<AppWrapper>{children}</AppWrapper>
);
}

Similar to layouts, templates allow you to create shared structure. We will not go into them deeply here, so I suggest that you read up on them on the Next.js documentation website.

Automatic code splitting

Next.js 13.4 also makes it easier than ever to code split and dynamically load content. In previous versions of Next.js you had to make use of next/dynamic. With Next.js 13, the entire application can opt into code splitting and dynamic loading by making use of Suspense . In fact, you can code split with a simple conditional within a client component. Check out the example below from the Next.js blog, which returns completely different bundles depending on whether the user is logged in or not:

// app/layout.tsx
import { getUser } from './auth';
import { Dashboard, Landing } from './components';

export default async function Layout() {
const isLoggedIn = await getUser();
return isLoggedIn ? <Dashboard /> : <Landing />;
}

More new features

Beyond the first stable release of the App Router, Next.js 13.4 also included some updates and releases of new features. We’ll take a look below at a few of these:

Server Actions (Alpha)

Next.js 13.4 introduces Server Actions (currently in alpha), which bring a whole new level of flexibility and power to your applications. Server Actions allow you to handle server-side logic, such as fetching data or interacting with APIs, directly in your application. This feature not only simplifies your application architecture but also enables you to create faster and more efficient applications.

For an in-depth look at Server Actions and how they’re transforming the way we build applications, check out my article: Why Next.js Server Actions are Game-Changing.

Turbopack: Now in Beta and More Feature Complete

With the release of Next.js 13.4, Turbopack has moved into the beta phase, offering a more feature-complete and stable experience. Turbopack is Next.js’s new Rust-based bundler designed to speed up local iterations in development and, soon, production builds. Thanks to the community’s support in testing and reporting bugs, Turbopack has grown in adoption, paving the way for a significantly faster and more efficient development experience in the future.

Draft Mode: Fetch and Render Draft Content Effortlessly

Next.js 13.4 introduces Draft Mode, a feature that allows you to fetch and render draft content from your headless CMS with ease. Draft Mode offers a more streamlined and enhanced experience compared to the existing Preview Mode API, which is not being supported in the new app directory.

With Draft Mode, you can now seamlessly preview and iterate on your content before publishing it, ensuring the highest quality output for your users.

Conclusion

Next.js 13.4 is a groundbreaking release that brings a plethora of new features and improvements to the table. From the first stable release of the app directory and app router to the introduction of Server Actions and Draft Mode, there are plenty of reasons to be excited about this release. As developers, we can now enjoy an even more streamlined and efficient development experience, ultimately leading to better applications for our users.

Start exploring all that Next.js 13.4 has to offer and take advantage of these fantastic features to create outstanding web applications!

Make sure to follow me for more content about Next.js and let me know in the comments if there’s another topic you’d like to hear about!

--

--

Ryan C. Collins
Frontend Weekly

Hey, I’m Ryan! I work in the Tech industry and post content about tech, leadership, and personal finance. https://www.ryanccollins.com

Recommended from Medium

Lists

See more recommendations