https://nextjs.org/blog/layouts-rfc
Deploy Next.js in seconds -
Skip to content
Next.js
Learn
ShowcaseDocsBlogAnalyticsExamplesEnterprise
Feedback
Email
[ ]
Feedback
[ ]
emojiemojiemojiemoji
Send
Learn
Layouts RFC
Monday, May 23rd 2022 ( ago)
[]Tim NeutkensTim Neutkens
Tim Neutkens@timneutkens
[]Sebastian MarkbageSebastian Markbage
Sebastian Markbage@sebmarkbage
[]Delba de OliveiraDelba de Oliveira
Delba de Oliveira@delba_oliveira
[]Lee RobinsonLee Robinson
Lee Robinson@leeerob
This RFC outlines the biggest update to Next.js since it was
introduced in 2016:
* Nested Layouts: Build complex applications with nested routes.
* Designed for Server Components: Optimized for subtree navigation.
* Improved Data Fetching: Fetch in layouts while avoiding
waterfalls.
* Using React 18 Features: Streaming, Transitions, and Suspense.
* Client and Server Routing: Server-centric routing with SPA-like
behavior.
* 100% incrementally adoptable: No breaking changes so you can
adopt gradually.
* Advanced Routing Conventions: Offscreen stashing, instant
transitions, and more.
The new Next.js router will be built on top of the recently released
React 18 features. We plan to introduce defaults and conventions to
allow you to easily adopt these new features and take advantage of
the benefits they unlock.
Timeline
This RFC will be divided into two parts:
* Part 1 (This Post): Overview of the new routing system and how it
integrates with React Server Components and Data Fetching.
* Part 2 (Next Post): Advanced routing examples and conventions,
and how Next.js will use Suspense behind the scenes for streaming
and selective hydration.
Motivation
We've been gathering community feedback from GitHub, Discord, Reddit,
and our developer survey about the current limitations of routing in
Next.js. We've found that:
* The developer experience of creating layouts can be improved. It
should be easy to create layouts that can be nested, shared
across routes, and have their state preserved on navigation.
* Many Next.js applications are dashboards or consoles, which would
benefit from more advanced routing solutions.
While the current routing system has worked well since the beginning
of Next.js, we want to make it easier for developers to build more
performant and feature-rich web applications.
As framework maintainers, we also want to build a routing system that
is backwards compatible and aligns with the future of React.
Terminology
This RFC introduces new routing conventions and syntax. The
terminology is based on React and standard web platform terms.
Throughout the RFC, you'll see these terms linked back to their
definitions below.
* 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 the tree, starting at the root (first) and ending
at the leaf (last).
[][yH5BAEAAAA][image]
* URL Path: Part of the URL that comes after the domain.
* URL Segment: Part of the URL path delimited by slashes.
[][yH5BAEAAAA][image]
How Routing Currently Works
Today, Next.js uses the file system to map individual folders and
files in the Pages directory to routes accessible through URLs. Each
Page file exports a React Component and has an associated Route based
on its file name. For example:
[][yH5BAEAAAA][image]
Next.js also supports Dynamic Routes (including catch all variations)
with the [param].js, [...param].js and [[...param]].js conventions.
* Layouts: Next.js offers support for simple component-based
layouts, per-page layouts using a component property pattern, and
a single global layout using a custom app.
* Data Fetching: Next.js provides data fetching methods (
getStaticProps, getServerSideProps) which can be used at the page
(route) level. These methods are used to determine if a page
should be Statically Generated (getStaticProps) or Server-Side
Rendered (getServerSideProps). In addition, you can use
Incremental Static Regeneration (ISR) to create or update static
pages after a site is built.
* Rendering: Next.js provides three rendering options: Static
Generation, Server-Side Rendering, and Client-Side Rendering. By
default, pages are statically generated unless they have a
blocking data fetching requirement (getServerSideProps).
Introducing the App Folder
To ensure these new improvements can be incrementally adopted and
avoid breaking changes, we are proposing a new directory called app.
[][yH5BAEAAAA][image]
The app directory will work alongside the pages directory. For
backwards compatibility, the behavior of the pages directory will
remain the same and continue to be supported. You can incrementally
move parts of your application to the new app directory to take
advantage of the new features.
Defining Routes
You can use the folder hierarchy inside app to define routes. A route
is a single path of nested folders, following the hierarchy from the
root folder down to the final leaf folder.
[][yH5BAEAAAA][image]
For example, you can add a new /dashboard/settings route by nesting
two new folders in the app directory.
Note:
+ With this system, you'll use folders to define routes, and
files to define UI (with new file conventions such as
layout.js, page.js, and in the second part of the RFC
loading.js).
+ This allows you to colocate your own project files (UI
components, test files, stories, etc) inside the app
directory. This is currently not possible in pages.
Route Segments
Each folder in the subtree represents a route segment. Each route
segment is mapped to a corresponding segment in a URL path.
[][yH5BAEAAAA][image]
For example, the /dashboard/settings route is composed of 3 segments:
* The / root segment
* The dashboard segment
* The settings segment
Note: The name route segment was chosen to match the existing
terminology around URL paths.
Layouts & Creating UI
New file convention: layout.js
So far, we have used folders to define the routes of our application.
But empty folders do not do anything by themselves. Let's discuss how
you can define the UI that will render for these routes using new
file conventions.
A layout is UI that is shared between route segments in a subtree.
Layouts do not affect URL paths and do not re-render (React state is
preserved) when a user navigates between segments that share the same
layout.
A layout can be defined by default exporting a React component from a
layout.js file. The component should accept a children prop which
will be populated with the segments the layout is wrapping.
There are 2 types of layouts:
* Root layout: Applies to all routes
* Regular layout: Applies to specific route segments
You can nest two or more layouts together to form nested layouts.
Root layout
You can create a root layout that will apply to all routes of your
application by adding a layout.js file inside the app folder.
[][yH5BAEAAAA][image]
Note:
+ The root layout replaces the need for a custom App (_app.js)
and custom Document (_document.js) since it applies to all
routes.
+ You'll be able to use the root layout to customize the
initial document shell (e.g. and
tags).
+ You'll be able to use data fetching methods inside the root
layout (and other layouts).
Regular layouts
You can also create a layout that only applies to a part of your
application by adding a layout.js file inside a specific folder.
[][yH5BAEAAAA][image]
For example, you can create a layout.js file inside the dashboard
folder which will only apply to the route segments inside dashboard.
Nesting layouts
Layouts are nested by default.
[][yH5BAEAAAA][image]
For example, if we were to combine the two layouts above. The root
layout (app/layout.js) would be applied to the dashboard layout,
which would also apply to all route segments inside dashboard/*.
[][yH5BAEAAAA][image]
Pages
New file convention: page.js
A page is UI that is unique to a route segment and required for a
route to be valid. You can create a page by adding a page.js file
inside a folder.
[][yH5BAEAAAA][image]
For example, to create pages for the /dashboard/* routes, you can add
a page.js file inside each folder. When a user visits /dashboard/
settings, Next.js will render the page.js file for the settings
folder wrapped in any layouts that exist further up the subtree.
[][yH5BAEAAAA][image]
You can create a page.js file directly inside the dashboard folder to
match the /dashboard route. The dashboard layout will also apply to
this page:
[][yH5BAEAAAA][image]
This route is composed of 2 segments:
* The / root segment
* The dashboard segment
Note:
+ For a route to be valid, it needs to have a page in its leaf
segment. If it doesn't, the route will 404.
+ A page.js file should default export a React component.
+ The name needs to be page.js exactly. If you do not export a
Page component, Next.js will throw an error.
Layout and Page Behavior
Recap:
* Page components are the default export of page.js.
* Layout components are the default export of layout.js.
* Layout components must accept a children prop.
When a layout component is rendered, the children prop will be
populated with a child layout component (if it exists further down
the subtree) or a page component.
It may be easier to visualize it as a layout tree where the parent
layout will pick the nearest child layout until it reaches a page.
Basic Example:
[][yH5BAEAAAA][image]
// Root layout (app/layout.js)
// - Applies to all routes
export default function RootLayout({ children }) {
return (
{children}
)
}
// Regular layout (app/dashboard/layout.js)
// - Applies to route segments in app/dashboard/*
export default function DashboardLayout({ children }) {
return (
<>
{children}
>
)
}
// Page Component (app/dashboard/analytics/page.js)
// - The UI for the `app/dashboard/analytics` segment
// - Matches the `acme.com/dashboard/analytics` URL path
export default function AnalyticsPage() {
return (
...
)
}
The above combination of layouts and pages would render the following
component hierarchy:
...
React Server Components
Note: If you're not familiar with React Server Components, we
recommend reading the React Server Component RFC before reading
this section.
With this RFC, you can start using React features and incrementally
adopt React Server Components into your Next.js application.
The internals of the new routing system leverage recently released
React features such as Streaming, Suspense, and Transitions. These
are the building blocks for React Server Components.
Server Components are the new default
One of the biggest changes between the pages and app directories is
that, by default, files inside app will be rendered on the server as
React Server Components.
This will allow you to automatically adopt React Server Components
when incrementally migrating your application from pages to app.
Rendering Environments and Component Types
Note: React introduces new component (module) types: Server,
Client, and Shared Components. To learn more about these new
types, we recommend reading the Capabilities & Constraints of
Server and Client Components and Server Module Conventions RFC.
You'll have granular control of what components will be in the
client-side JavaScript bundle using the new React conventions. There
is an ongoing discussion on what exactly the convention will be for
defining Client Components and Server Components. We will follow the
resolution of this discussion.
For now, it's worth noting that app allows components (layouts and
pages) in a route to be rendered on the server, on the client, or
both.
[][yH5BAEAAAA][image]
This is different from the pages directory in Next.js, where by
default, pages are statically generated unless they have data
fetching requirements. In pages, you have the flexibility to decide
when (build time or runtime) and where (server-side, client-side, or
a combination) a page is rendered by using Next.js data fetching
methods (getStaticProps, getServerSideProps) or fetching the data
from the client-side
However, in the app folder, the rendering environment is decoupled
from the data fetching method and set at the component level. You
will still need to respect the constraints of Client and Server
components (e.g. you will not be able to use the getServerSideProps
method inside a page or layout that is a client component).
Interleaving Client and Server Components using the children prop
In React, there's a restriction around importing Server Components
inside Client Components because Server Components might have
server-only code that should only run on the server (e.g. database or
filesystem utilities).
For example, this pattern would not work:
import ServerComponent from './ServerComponent.js';
export default function ClientComponent() {
return (
<>
>
);
}
However, a Server Component can be passed as a child of a Client
Component if both are wrapped in another Server Component. For
example, you can pass the ServerComponent to the ClientComponent as a
child in another Server Component.
// ClientComponent.js
export default function ClientComponent({ children }) {
return (
<>
Client Component
{children}
>
);
}
// ServerComponent.js
export default function ServerComponent() {
return (
<>
Server Component
>
);
}
// page.js
// It's possible to import Client and Server components inside Server Components
// because this component is rendered on the server
import ClientComponent from "./ClientComponent.js";
import ServerComponent from "./ServerComponent.js";
export default function ServerComponentPage() {
return (
<>
>
);
}
With this pattern, React will know it needs to render ServerComponent
on the server before sending the result (which doesn't contain any
server-only code) to the client. From the Client Component's
perspective, its child will be already rendered.
The new router leverages this to allow rendering layouts as client
components while the nested layout or page might be a server
component.
For example, you can have a Server Component page and a Client
Component layout wrapping it:
// The Dashboard Layout is a Client Component
// app/dashboard/layout.js
export default function ClientLayout({ children }) {
// Can use useState / useEffect here
return (
<>
Layout
{children}
>
);
}
// The Page is a Server Component that will be passed to Dashboard Layout
// app/dashboard/settings/page.js
export default function ServerPage() {
return (
<>
Page
>
);
}
Note: This style of composition is an important pattern for
rendering Server Components inside Client Components. It sets the
precedence of one pattern to learn, and is one of the reasons why
we've decided to use the children prop.
Data fetching
It's possible to use Next.js data fetching methods inside layout.js
files. Since layouts can be nested, this also means it is possible to
fetch data in multiple segments of a route. This is different from
the pages directory, where data fetching methods were limited to the
page-level.
Data fetching in Layouts
You can fetch data in a layout.js file by using the Next.js data
fetching methods getStaticProps or getServerSideProps.
For example, a blog layout could use getStaticProps to fetch
categories from a CMS, which can be used to populate a sidebar
component:
// app/blog/layout.js
export async function getStaticProps() {
const categories = await getCategoriesFromCMS();
return {
props: { categories },
};
}
export default function BlogLayout({ categories, children }) {
return (
<>
{children}
>
);
}
Multiple data fetching methods in a route
You can also fetch data in multiple segments of a route. For example,
a layout that fetches data can also wrap a page that fetches its own
data.
Using the blog example above, a single post page can use
getStaticProps and getStaticPaths to fetch post data from a CMS:
// app/blog/[slug]/page.js
export async function getStaticPaths() {
const posts = await getPostSlugsFromCMS();
return {
paths: posts.map((post) => ({
params: { slug: post.slug },
})),
};
}
export async function getStaticProps({ params }) {
const post = await getPostFromCMS(params.slug);
return {
props: { post },
};
}
export default function BlogPostPage({ post }) {
return ;
}
Since both app/blog/layout.js and app/blog/[slug]/page.js use
getStaticProps, Next.js will statically generate the whole /blog/
[slug] route as React Server Components at build time. React Server
Components result in less client-side JavaScript and faster
hydration.
Statically generated routes improve this further, as the client
navigation reuses the cache (server components data) and doesn't
recompute work, leading to less CPU time because you're rendering a
snapshot of the Server Components.
Behavior and priority
Next.js Data Fetching Methods (getServerSideProps and getStaticProps)
can only be used in Server Components in the app folder. Different
data fetching methods in segments across a single route affect each
other.
Using getServerSideProps in one segment will affect getStaticProps in
other segments. Since a request already has to go to a server for the
getServerSideProps segment, the server will also render any
getStaticProps segments. It will reuse the props fetched at build
time so the data will still be static, the rendering happens
on-demand on every request with the props generated during next
build.
Using getStaticProps with revalidate (ISR) in one segment will affect
getStaticProps with revalidate in other segments. If there are two
revalidate periods in one route, the shorter revalidation will take
precedence.
Note: In the future, this may be optimized to allow for full data
fetching granularity in a route.
Data fetching and rendering with React Server Components
The combination of Server-Side Routing, React Server Components,
Suspense and Streaming have a few implications for data fetching and
rendering in Next.js:
Parallel fetching and rendering
Next.js will eagerly initiate data fetches in parallel to minimize
waterfalls. In combination with Suspense, React can also start
rendering Server Components immediately, before the requests have
completed, and can slot in the result as the requests resolve.
For example, if data fetching was sequential, each nested segment in
the route couldn't start fetching data until the previous segment was
completed. If rendering was dependent on data fetching, each segment
could only render after data fetching was complete.
[][yH5BAEAAAA][image]
Partial fetching and rendering
When navigating between sibling route segments, Next.js will only
fetch and render from that segment down. It will not need to re-fetch
or re-render anything above. This means in a page that shares a
layout, the layout will be preserved when a user navigates between
sibling pages, and Next.js will only fetch and render from that
segment down.
This is especially useful for React Server Components, as otherwise
each navigation would cause the full page to re-render on the server
instead of rendering only the changed part of the page on the server.
This reduces the amount of data transfered and execution time,
leading to improved performance.
For example, if the user navigates between the /analytics and the /
settings pages, React will re-render the page segments but preserve
the layouts:
[][yH5BAEAAAA][image]
Note: It will be possible to force a re-fetch of data higher up
the tree. We are still discussing the details of how this will
look and will update the RFC.
Conclusion
We're excited about the future of layouts, routing, and data fetching
in Next.js. In the next part of the RFC, we'll discuss:
* Instant Loading States: With server-side routing, rendering and
data fetching happens on the server before navigation completes.
This makes it important to show loading UI so the application
doesn't feel unresponsive. We propose framework level support for
instant loading states - inline and global loading indicators and
skeletons.
* Offscreen Stashing with Instant Back/Forward: React is planning
to add a new component that stores a React tree and
its state without rendering it to the screen. Leveraging this
component, it should be possible to stash routes that have been
visited and pre-render routes before they are visited. Navigation
backwards and forwards to these routes should be instant and
restore any previously stored state.
* Parallel Routes: If you have two or more tab bars on a page, it
should be possible to have two or more parallel nested layouts
that can be navigated independently, conceptually similar to an
.
* Intercepting Routes: Sometimes it's useful to be able to
intercept a route from within another page. The URL would
normally lead to a different part of the UI but not when it's
visited within this context. For example, a tweet that can be
expanded and presented inline or a modal photo viewer instead of
a standalone gallery.
* Streaming and selective hydration: We will share more details
about how a server centric routing, React Server Components,
Suspense and streaming combine to enable new routing paradigms
and help performance by reducing what is sent to the client and
breaking down work into smaller chunks.
Leave comments and join the conversation on GitHub Discussions.
- Back to Blog
---------------------------------------------------------------------
Was this helpful?
uselessnoyesamazing
Email
[ ]
Feedback
[ ]
Send
General resources
Docs
Learn
Showcase
Blog
Analytics
Next.js Conf
Live
More
Commerce
Contact Sales
GitHub
Releases
Telemetry
About Vercel
Open Source Software
GitHub
Twitter
Legal
Privacy Policy
Copyright (c) 2022 Vercel, Inc. All rights reserved.