Server-Side Rendering (SSR)
- All data for a given page is fetched on the server.
- The server then renders the HTML for the page.
- The HTML, CSS, JS for the page are sent to the client.
- A non-interactive user interface is shown using the generated HTML, CSS.
- Finally, React hydrates the user interface to make it interactive.
If the data takes long time to load, then the website would be not interactive. To resolve this issue Streaming is used
- Since the UI is broken into React components (chunks), the chunks that do not depend on data or with high priority can be sent first. This includes sending the
- Low priority chunks like product reviews, related products can be sent later.
- In short, Streaming prevents long data requests from blocking the page from rendering.
- To implement this use
Also, internally streaming would only start after all the data for
generateMetadatais fetched, so as to include the
app/page.tsx- maps to
app/dashboard/page.tsx- maps to
/dashboard. (static route)
app/blog/[slug]/page.tsx- maps to
app/blog/[...slug]/page.tsx- maps to
app/blog/[[...slug]]/page.tsx- maps to
/blog/a/b(optional catch-all segments)
app/@team/members- used to define parallel routes.
page.jsdefines the leaf node in the route hiearchy and makes that URL publickly accessible.
Linking and Navigating
<Link> instead of
<a> to get prefetching and client-side navigation between routes.
To check if the current path is active use
<Link> tags becomes visible in the viewport, it is prefetches (if it is static route). For dynamic routes, only the shared layout and
loading.tsx is prefetched and cached for 30s. To programmatically control the behavior of Link and caching use
Also, the scroll position is preserved between forwards and backwards navigation.
This allows you to organize files into folders, without affecting the route URL. Let's say you have a file
app/marketing/about/page.js which would be renderd at
But if you want to exclude
marketing from the route name, you can wrap it in brackets as
app/(marketing)/about/page.js and then it would be rendered at
This allows to organize route segments and project files into logical groups without affecting the URL path structure.
Wrap folder name in square brackets like
[id], and these are passed as
params to layout, page, route, generateMetadata functions.
To generate routes dynamically every time a request is made use this
To generate routes during build time use this
Simulaneously or conditionally render one or more pages in the same layout, which is useful on highly dynamic sections of an app like dashboards and feeds (you can simultaneously render the team and analytics page), and this also includes conditional slots based on authentication state.
Define a folder starting with
In the above case
app/@analytics/page.js gets routed to
/ as parallel routes do not affect URL structure.
Now you can load both the slots in parallel in
For conditional routing it is the same logic
To know which route segment is active you can use this code
You can also define a
default.js file to render as a fallback in case Next.js cannot recover a slot's active state based on the current url.
layout.tsx- Shared UI for a segment (directory) and its children. On navigation, layouts preserve state, remain interactive, and do no re-render.
page.tsx- Unique UI of a route and make routes publicly accessible
loading.tsx- Loading UI for a segment and its children
not-found.tsx- Not found UI for a segment and its children
error.tsx- Error UI for a segment and its children
global-error.tsx- Global Error UI
route.tsx- Server side API endpoint
template.tsx- Specialized re-rendered Layout UI
default.tsx- Fallback UI for parallel routes
Internally these are rendered as
app/layout.tsx should contain
RootLayout and it defines
<body> tags, shared across all pages in an application.
loading.tsx creates loading UI with React Suspense. This is shown while the content of a route segment loads. The new content is automatically swapped in once rendering is complete. Also, the loading can be interrupted if navigating to another page.
Internally this gets translated to
error.js to handle unexpected runtime errors. This has the benefit
- Create a specific UI for the error.
- Isolate errors to affected segments while keeping the rest of the application functional.
- Add functionality to attempt to recover from an error without a full page reload.
Internally, it uses React error boundary as
error.js does not catch errors thrown in
template.js in the same folder. This keeps the layout interactive when an error with a component occurs.
To handle erros for
template.js, place an
error.js file in parent folder.
TO handle errors for the root
template file create
app/global-error.js. You would rarely reach this error boundary, but it is a good practice to still define this file, and include globally shared UI and branding.
Do not use
<head> tags, because the next solutions handle de-duplication and streaming.
Use metadata object
Generate metadata dynamically
Next.js supports creating
route.ts (the directory should not contain
page.js) files to define HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS). This is the same as defining these routes in Express. The main difference is when you use Express, you have to host a dedicated server that needs to be running all the time. But Next.js uses AWS Lambda (serverless functions) for this.
You still need API routes. Consider these two cases - Server side components - These can directly make the backend calls, as the server code is never shown to the client. - Client side components - These can directly make the backend calls, but this might requrie sharing some sensitive info to the client. For this reason, you make the call the "API Route" created by Next.js which then makes the call to your backend.
Created: November 21, 2023