Next.js 13: The Most Exciting New Features for JavaScript Developers
Introduction
Next.js is the most popular full-stack JavaScript framework, and its latest version is packed with exciting new features. In this article, we’ll explore the most important changes and how they can help you build faster, more scalable, and more user-friendly applications.
Firstly, let’s create Next 13 application by running the following command
npx create-next-app@latest --ts myapp
This will create a next.js 13 application.
Topics covered
Here are some of the new changes we will be diving into in this article:
- App directory replaces pages
- Turbopack
- Layout
- Server components
- Data fetching
- Image component, Font system, and Link
App directory replaces the pages directory
Remove the pages
directory and add a new directory named app
and create a page.tsx
file instead of a index.tsx
like you would do in the older versions.
Turbopack
Vercel, the company that owns Next.js, has also released its own build tool named Turbopack
Using the Turbopack with Next.js 13 results in:
- 700x faster updates than Webpack
- 10x faster updates than Vite
- 4x faster cold starts than Webpack
Turbopack only bundles the minimum assets required in development, so startup time is extremely fast. On an application with 3,000 modules, Turbopack takes 1.8 seconds to boot up. Vite takes 11.4 seconds and Webpack takes 16.5 seconds.
Go into the package.json
file and add the --turbopack
extension to the next dev
command like this:
dev: next dev --turbo
Then run, npm run dev
Add layout and global.css
You should also consider adding a layout.tsx
file and a global.css
file to the app
directory. Here are some important uses for these two files if you are new to Next.js
- Layout.tsx: Add headers and footers to the layout for code reusability and to adhere to the DRY (Don’t repeat yourself) principle. Also, you can nest layouts, to apply customizability so that you can apply different styles to different sub-routes. And finally, you can fetch data in layouts as well, so that you don’t have to fetch data on each page.
- Global.css: A simple global CSS file that you can use to apply styles to every component and page in your Next.js file.
Server Components
Next.js 13 introduces support for React’s new Server Components architecture. This allows you to build fast, highly interactive apps using a single programming model, with the server and client each handling the tasks they’re best at.
Server Components are a fundamental change in the way Next.js renders pages. Previously, Next.js rendered pages entirely on the server or entirely on the client. With Server Components, Next.js can now render pages in a hybrid fashion, with parts of the page being rendered on the server and other parts being rendered on the client.
This hybrid rendering approach has a number of benefits, including:
- Faster initial page loads: Server Components can be used to render the static parts of a page on the server, while the dynamic parts are rendered on the client. This can significantly improve the initial page load time, especially for pages with a lot of dynamic content.
- Reduced JavaScript bundle size: Server Components can also be used to reduce the size of the JavaScript bundle that is sent to the client. This is because only the dynamic parts of the page need to be sent to the client, while the static parts can be rendered directly from the server.
- Improved developer experience: Server Components provide a single programming model for building both server-rendered and client-rendered apps. This makes it easier to develop and maintain complex applications.
Here is a short example of how to use Server Components to fetch data from a public API:
import { ServerComponent } from 'next/server';
async function fetchPosts() {
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
return posts;
}
function PostsList({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
export default function IndexPage() {
const posts = await fetchPosts();
return (
<ServerComponent>
<PostsList posts={posts} />
</ServerComponent>
);
}
This example uses the ServerComponent
component to render the PostsList
component on the server. The fetchPosts
function is called on the server to fetch the list of posts from the public API. The PostsList
component is then rendered with the list of posts as props.
When the user visits the /
page, Next.js will render the PostsList
component on the server and send the rendered HTML to the client. This means that the user will see the list of posts immediately, without having to wait for the client to fetch the data from the API.
Server Components are a powerful new feature in Next.js 13 that can be used to build fast, highly interactive apps with a single programming model.
Data fetching
Next.js 13 introduces support for React’s new Promises RFC, which makes it easier to fetch data and handle promises inside components.
Here is a modified version of the previous example that uses promises to fetch the list of posts from the public API:
// pages/index.js
import { ServerComponent } from 'next/server';
async function getData() {
const response = await fetch('https://api.example.com/posts');
const posts = await response.json();
return posts;
}
function PostsList({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
export default async function IndexPage() {
const posts = await getData();
return (
<ServerComponent>
<PostsList posts={posts} />
</ServerComponent>
);
}
The main difference between this example and the previous one is that the fetchPosts
function now returns a promise instead of an array of posts. This allows us to use the async
and await
keywords to wait for the promise to resolve before rendering the PostsList
component.
Another difference is that we are now using the ServerComponent
component to render the PostsList
component on the server. This means that the list of posts will be fetched from the API on the server and the rendered HTML will be sent to the client. This will improve the initial page load time, especially for users who have a slow internet connection.
Native fetch API Extensions
The native fetch Web API has also been extended in React and Next.js. These extensions make it easier to cache and revalidate data at the component level.
For example, to fetch data and cache it until manually invalidated, you can use the following code:
fetch(URL, { cache: 'force-cache' });
This is similar to using the getStaticProps
function.
To fetch data and refetch it on every request, you can use the following code:
fetch(URL, { cache: 'no-store' });
This is similar to using the getServerSideProps
function.
To fetch data and cache it with a lifetime of 10 seconds, you can use the following code:
fetch(URL, { next: { revalidate: 10 } });
This is similar to using the getStaticProps
function with the revalidate
option.
Server-side data fetching with promises and the native fetch API extensions is a powerful way to improve the performance and developer experience of your Next.js applications.
Image Component: Faster, Easier, and More Accessible
Next.js 13’s new Image component makes it easy to display images without layout shift and optimize them on-demand for better performance. This means that your images will load quickly and look great on all devices, without causing your page layout to shift around as they load.
The new Image component is also easier to style and configure, and it requires alt tags by default, making your images more accessible. Additionally, it aligns with the Web platform and is faster because it uses native lazy loading, which doesn’t require hydration.
Here are some of the key benefits of the new Next.js 13 Image component:
- Less client-side JavaScript: The new Image component ships less client-side JavaScript, which makes your pages load faster and reduces memory usage.
- Easier to style and configure: The new Image component is easier to style and configure than the previous version. It also provides a number of new features, such as the ability to specify a layout and loader.
- More accessible: The new Image component requires alt tags by default, making your images more accessible to users with disabilities.
- Aligned with the Web platform: The new Image component aligns with the Web platform, which means that it is compatible with all major browsers and devices.
- Faster: The new Image component is faster than the previous version because it uses native lazy loading, which doesn’t require hydration.
If you’re using Next.js, I encourage you to upgrade to the new Image component as soon as possible. It’s a significant improvement over the previous version and it will make your images load faster and look better.
import Image from 'next/image';
import avatar from './lee.png';
export default function Home() {
// "alt" is now required for improved accessibility
// optional: image files can be colocated inside the app/ directory
return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}
Font System: Faster, More Private, and Easier to Use
Next.js 13 introduces a new font system that automatically optimizes your fonts, removes external network requests, and self-hosts your fonts with your static assets. This means that your fonts will load faster and more privately, without causing your page layout to shift as they load.
The new font system also makes it easier to use Google Fonts. CSS and font files are downloaded at build time and self-hosted with the rest of your static assets, so you don’t have to worry about making any changes to your code.
Here are some of the key benefits of the new Next.js 13 font system:
- Faster: The new font system optimizes your fonts and removes external network requests, resulting in faster page loads.
- More private: The new font system self-hosts your fonts with your static assets, so you don’t have to send any requests to Google.
- Easier to use: The new font system makes it easier to use Google Fonts, without having to make any changes to your code.
If you’re using Next.js, I encourage you to upgrade to the new font system as soon as possible. It’s a significant improvement over the previous version and it will make your fonts load faster and more privately.
app/layout.js / pages/_app.js
import { Inter } from '@next/font/google';
const inter = Inter();
<html className={inter.className}></html>;
Custom fonts are also supported, including support for automatic self-hosting, caching, and preloading of font files.
app/layout.js / pages/_app.js
import localFont from '@next/font/local';
const myFont = localFont({ src: './my-font.woff2' });
<html className={myFont.className}></html>;
You can customize every part of the font loading experience while still ensuring great performance and no layout shift, including the font-display
, preloading, fallbacks, and more.
Link Component
The Next.js 13 Link component no longer requires you to manually add a <a>
tag as a child. This was added as an experimental option in version 12.2 and is now the default. In Next.js 13, <Link>
always renders a <a>
tag and allows you to forward props to the underlying tag.
This means that you can now write code like this:
<Link href="/about">About</Link>
Instead of:
<Link href="/about">
<a>About</a>
</Link>
This makes your code more concise and easier to read.
Conclusion
Next.js 13 is a major release that introduces a number of exciting new features and changes. These updates make Next.js even faster, more scalable, and more user-friendly.
If you’re already using Next.js, I encourage you to upgrade to version 13 as soon as possible. If you’re new to Next.js, now is the perfect time to start learning. It’s the best way to build fast, scalable, and user-friendly JavaScript applications.
Here are some of the key benefits of using Next.js 13:
- Improved performance: Next.js 13 is faster than ever before, thanks to Turbopack and other improvements.
- Increased scalability: Next.js 13 is more scalable than ever before, thanks to the new app directory and other features.
- Improved developer experience: Next.js 13 makes it easier to develop and maintain complex applications, thanks to layouts, server components, and other features.
If you’re looking for a framework that can help you build fast, scalable, and user-friendly JavaScript applications, Next.js 13 is the perfect choice.