Next.js is a React framework for building full-stack web applications. You use React Components to build user interfaces, and Next.js for additional features and optimizations.
Under the hood, Next.js also abstracts and automatically configures tooling needed for React, like bundling, compiling, and more. This allows you to focus on building your application instead of spending time with configuration.
Some of the main Next.js features include:
Feature | Description |
---|---|
Routing | A file-system based router built on top of Server Components that supports layouts, nested routing, loading states, error handling, and more. |
Rendering | Client-side and Server-side Rendering with Client and Server Components. Further optimized with Static and Dynamic Rendering on the server with Next.js. Streaming on Edge and Node.js runtimes. |
Data Fetching | Simplified data fetching with async/await in Server Components, and an extended fetch API for request memoization, data caching and revalidation. |
Styling | Support for your preferred styling methods, including CSS Modules, Tailwind CSS, and CSS-in-JS |
Optimizations | Image, Fonts, and Script Optimizations to improve your application's Core Web Vitals and User Experience. |
TypeScript | Improved support for TypeScript, with better type checking and more efficient compilation, as well as custom TypeScript Plugin and type checker. |
Next.js has two different routers: the App Router and the Pages Router.
The App Router is a newer router that allows you to use React's latest features, such as Server Components and Streaming.
The Pages Router is the original Next.js router, which allowed you to build server-rendered React applications and continues to be supported for older Next.js applications.
- Node.js 18.17 or later.
- macOS, Windows (including WSL), and Linux are supported.
npx create-next-app@latest
On installation, you'll see the following prompts:
What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/*
After the prompts, create-next-app
will create a folder with your project name and install the required dependencies.
To manually create a new Next.js app, install the required packages:
npm install next@latest react@latest react-dom@latest
Open your package.json
file and add the following scripts
:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}
These scripts refer to the different stages of developing an application:
dev
: runs[next dev](https://nextjs.org/docs/app/api-reference/next-cli#development)
to start Next.js in development mode.build
: runs[next build](https://nextjs.org/docs/app/api-reference/next-cli#build)
to build the application for production usage.start
: runs[next start](https://nextjs.org/docs/app/api-reference/next-cli#production)
to start a Next.js production server.lint
: runs[next lint](https://nextjs.org/docs/app/api-reference/next-cli#lint)
to set up Next.js' built-in ESLint configuration.
Creating Directories
Next.js uses file-system routing, which means the routes in your application are determined by how you structure your files.
The app
Directory
For new applications, we recommend using the App Router.
This router allows you to use React's latest features and is an evolution of the Pages Router based on community feedback.
Create an app/
folder, then add a layout.tsx
and page.tsx
file. These will be rendered when the user visits the root of your application (/
).
Create a root layout inside app/layout.tsx
with the required <html>
and <body>
tags:
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Finally, create a home page app/page.tsx
with some initial content:
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
Good to know: If you forget to create
layout.tsx
, Next.js will automatically create this file when running the development server withnext dev
.
The pages
Directory (Optional)
If you prefer to use the Pages Router instead of the App Router, you can create a pages/
directory at the root of your project.
Then, add an index.tsx
file inside your pages
folder. This will be your home page (/
):
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
Next, add an _app.tsx
file inside pages/
to define the global layout. Learn more about the custom App file.
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
Finally, add a _document.tsx
file inside pages/
to control the initial response from the server. Learn more about the custom Document file.
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Learn more about using the Pages Router.
The public
folder (Optional)
Create a public
folder to store static assets such as images, fonts, etc. Files inside public
directory can then be referenced by your code starting from the base URL (/
).
- Run
npm run dev
to start the development server. - Visit
http://localhost:3000
to view your application. - Edit
app/page.tsx
(orpages/index.tsx
) file and save it to see the updated result in your browser.
Routing Fundamentals
The skeleton of every application is routing. This page will introduce you to the fundamental concepts of routing for the web and how to handle routing in Next.js.
Terminology
First, you will see these terms being used throughout the documentation. Here's a quick reference:
terminology-component-tree.avif
- Tree: A convention for visualizing a hierarchical structure. For example, a component tree with parent and children components, a folder structure, etc.
- Subtree: Part of a tree, starting at a new root (first) and ending at the leaves (last).
- Root: The first node in a tree or subtree, such as a root layout.
- Leaf: Nodes in a subtree that have no children, such as the last segment in a URL path.
- URL Segment: Part of the URL path delimited by slashes.
- URL Path: Part of the URL that comes after the domain (composed of segments).
The app
Router
In version 13, Next.js introduced a new App Router built on React Server Components, which supports shared layouts, nested routing, loading states, error handling, and more.
The App Router works in a new directory named app
. The app
directory works alongside the pages
directory to allow for incremental adoption. This allows you to opt some routes of your application into the new behavior while keeping other routes in the pages
directory for previous behavior. If your application uses the pages
directory, please also see the Pages Router documentation.
Good to know: The App Router takes priority over the Pages Router. Routes across directories should not resolve to the same URL path and will cause a build-time error to prevent a conflict.
By default, components inside app
are React Server Components. This is a performance optimization and allows you to easily adopt them, and you can also use Client Components.
Recommendation: Check out the Server page if you're new to Server Components.
Roles of Folders and Files
Next.js uses a file-system based router where:
- Folders are used to define routes. A route is a single path of nested folders, following the file-system hierarchy from the root folder down to a final leaf folder that includes a
page.js
file. See Defining Routes. - Files are used to create UI that is shown for a route segment. See special files.
Route Segments
Each folder in a route represents a route segment. Each route segment is mapped to a corresponding segment in a URL path.
route-segments-to-path-segments.avif
Nested Routes
To create a nested route, you can nest folders inside each other. For example, you can add a new /dashboard/settings
route by nesting two new folders in the app
directory.
The /dashboard/settings
route is composed of three segments:
/
(Root segment)dashboard
(Segment)settings
(Leaf segment)
File Conventions
Next.js provides a set of special files to create UI with specific behavior in nested routes:
layout | Shared UI for a segment and its children |
---|---|
page | Unique UI of a route and make routes publicly accessible |
loading | Loading UI for a segment and its children |
not-found | Not found UI for a segment and its children |
error | Error UI for a segment and its children |
global-error | Global Error UI |
route | Server-side API endpoint |
template | Specialized re-rendered Layout UI |
default | Fallback UI for Parallel Routes |
Good to know:
.js
,.jsx
, or.tsx
file extensions can be used for special files.
Also referred to as SSR or Dynamic Rendering.
If a page uses Server-side Rendering, the page HTML is generated on each request.
To use Server-side Rendering for a page, you need to export
an async
function called getServerSideProps
. This function will be called by the server on every request.
For example, suppose that your page needs to pre-render frequently updated data (fetched from an external API). You can write getServerSideProps
which fetches this data and passes it to Page
like below:
export default function Page({ data }) {
// Render data...
}
// This gets called on every request
export 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 } }
}
As you can see, getServerSideProps
is similar to getStaticProps
, but the difference is that getServerSideProps
is run on every request instead of on build time.
Also referred as CSR or Static Rendering.
In Client-Side Rendering (CSR) with React, the browser downloads a minimal HTML page and the JavaScript needed for the page. The JavaScript is then used to update the DOM and render the page.
When the application is first loaded, the user may notice a slight delay before they can see the full page, this is because the page isn't fully rendered until all the JavaScript is downloaded, parsed, and executed.
After the page has been loaded for the first time, navigating to other pages on the same website is typically faster, as only necessary data needs to be fetched, and JavaScript can re-render parts of the page without requiring a full page refresh.
In Next.js, there are two ways you can implement client-side rendering:
- Using React's
useEffect()
hook inside your pages instead of the server-side rendering methods (getStaticProps
andgetServerSideProps
). - Using a data fetching library like SWR or TanStack Query to fetch data on the client (recommended).
Here's an example of using useEffect()
inside a Next.js page:
import React, { useState, useEffect } from 'react'
export function Page() {
const [data, setData] = useState(null)
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data')
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result = await response.json()
setData(result)
}
fetchData().catch((e) => {
// handle the error as needed
console.error('An error occurred while fetching the data: ', e)
})
}, [])
return <p>{data ? `Your data: ${data}` : 'Loading...'}</p>
}
In the example above, the component starts by rendering Loading...
. Then, once the data is fetched, it re-renders and displays the data.
Although fetching data in a useEffect
is a pattern you may see in older React Applications, we recommend using a data-fetching library for better performance, caching, optimistic updates, and more. Here's a minimum example using SWR to fetch data on the client:
import useSWR from 'swr'
export function Page() {
const { data, error, isLoading } = useSWR(
'https://api.example.com/data',
fetcher
)
if (error) return <p>Failed to load.</p>
if (isLoading) return <p>Loading...</p>
return <p>Your Data: {data}</p>
}
Good to know:
Keep in mind that CSR can impact SEO. Some search engine crawlers might not execute JavaScript and therefore only see the initial empty or loading state of your application. It can also lead to performance issues for users with slower internet connections or devices, as they need to wait for all the JavaScript to load and run before they can see the full page. Next.js promotes a hybrid approach that allows you to use a combination of server-side rendering, static site generation, and client-side rendering, depending on the needs of each page in your application. In the App Router, you can also use Loading UI with Suspense to show a loading indicator while the page is being rendered.