Next.js 13 tutorial with new features
In this tutorial we'll learn about the new features of Next.js 13 by building a demo web application from scratch.
Creating a Next.js 13 app
Let's get started by installing Next.js 13. Head over to a new terminal and run the following command:
npx create-next-app@latest
You'll be prompted as follows:
✔ What is your project named? … next13demo
✔ Would you like to use TypeScript with this project? … No / Yes
✔ Would you like to use ESLint with this project? … No / Yes
I named the app next13demo
and answered No
for the other questions!
Next.js 13 app directory
Since this is a tutorial about the new features of Next.js 13, we'll use the app/
directory which aims to improve routing and layouts in Next.js.
This is still an experimental feature so we need to enable it. Open the next.config.js
file and update it as follows:
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: { appDir: true }
}
module.exports = nextConfig
Next, create the app/
directory with a page.jsx
file and the following contents:
export default function Page() {
return <p>Hello, Next.js 13</p>;
}
Before you proceed, you need to remove the pages/index.js
or Next.js 13 will throw the following error: error - Conflicting app and page file was found, please remove the conflicting files to continue.
After that start the dev server using the following command from the root of your Next.js 13 project:
npm run dev
You'll get the following output
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
warn - You have enabled experimental feature (appDir) in next.config.js.
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
info - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback
event - compiled client and server successfully in 546 ms (208 modules)
wait - compiling /page (client and server)...
Your page app/page.jsx did not have a root layout, we created app/layout.js for you.
You'll be able to visit your Next.js 13 web app from http://localhost:3000/
.
Next.js 13 layouts
You can see that Next created an app/layout.js
for us with the following contents:
export default function RootLayout({ children }) {
return (
<html>
<head></head>
<body>{children}</body>
</html>
)
}
The layout function accepts a layout or a page as a child. Accodring to the official website:
A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not re-render.
Layouts are a great feature that enables developers to share common logic between pages.
For example, we can put the top navigation menu in the app/layout.js
file. Create a app/navbar.jsx
file and add the following contents:
import Link from "next/link";
export default () => {
return (
<ul>
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/user/login">Login</Link>
</li>
<li>
<Link href="/user/signup">Sign Up</Link>
</li>
</ul>
);
};
Next, update the app/layout.js
file as follows:
import Navbar from "./navbar";
export default function RootLayout({ children }) {
return (
<html>
<head></head>
<body>
<Navbar />
{children}
</body>
</html>
)
}
You can then create the other two pages inside tha app/
folder in the same way. Create app/user/login/page.jsx
with the following contents:
export default function Page() {
return <p>Login</p>;
}
Then create the app/user/signup/page.jsx
with the following contents:
export default function Page() {
return <p>Signup</p>;
}
React Server Components vs. Client Components
In Next.js 13 all components inside the app directory are React Server Components by default. You can use the use client
directive at the top of the component designed for the client.
Let's make the navigation component a client component. Open the app/navbar.jsx
file and update it as follows:
"use client";
import Link from "next/link";
export default () => {
return (
<ul>
<li>
<Link href="/">Home</Link>
</li>
<li>
<Link href="/user/login">Login</Link>
</li>
<li>
<Link href="/user/signup">Sign Up</Link>
</li>
</ul>
);
};
You specifically must add use client
when:
- Making use of
useState
oruseEffect
hooks from React - Making use of some browser APIs
- You need to add certain event listeners
In other circumstances, where you don't need something from the client, it's ideal to leave components alone and let Next.js render them as Server Components. This will assist to guarantee that there is as little client-side JavaScript code as possible.
Next.js 13 nested layouts
We can also use nested layouts. Inside the user/
sub route we can add a layout.jsx
with the following contents:
export default function UserLayout({ children }) {
return (
<main>
<h2>Auth</h2>
{children}
</main>
)
}
If your visit your Next.js 13 app, you can see that we've a shared UI between the three pages and thanks to the sub-route layout, we also have a shared UI that contains the Auth header between the two pages of the user/
route.
-
Date: