Next.js Fundamentals
Core concepts of Next.js including routing, rendering strategies, and data fetching.
Key Concepts
+ Add ConceptNext.js Parallel and Intercepting Routes
Next.js Parallel and Intercepting Routes
Next.js provides advanced routing mechanisms to handle complex UI requirements.
Parallel Routes
Allow you to simultaneously or conditionally render one or more pages in the same layout. They are defined using “slots” (e.g., @team and @analytics).
- Use Case: Dashboards with independent sections, split-screen views.
Intercepting Routes
Allow you to load a route from another part of your application within the current layout.
- Convention:
(.)to match segments on the same level,(..)for one level above, etc. - Use Case: “Modals” where clicking an image opens it in a modal over the current page, but refreshing the page loads the image on its own page.
Next.js App Router
Next.js App Router
The App Router is the modern system for building Next.js applications, introduced in Next.js 13 and becoming the default in Next.js 14 and 15. It is built on React’s latest features, including Server Components and Streaming.
Key Features
- Server Components: Components that run on the server and reduce the amount of JavaScript sent to the client.
- File-based Routing: Routes are defined by folders, with
page.jsfiles acting as the entry point. - Nested Layouts: Easily share UI between routes using
layout.js. - Streaming: The ability to send chunks of the UI to the client as they are generated.
Authentication Patterns
Next.js Authentication Patterns
Authentication in Next.js (especially the App Router) revolves around where the session is stored and how it is accessed.
Session Strategies
- Server-side Sessions (HTTP-only Cookies): The preferred method for security. Sessions are read in Middleware, Server Components, and Route Handlers.
- Client-side Sessions (JWT in LocalStorage): Less secure and generally discouraged in modern Next.js apps as they can’t be accessed by Server Components during pre-rendering.
Protection Mechanisms
- Middleware: The first line of defense. Used to redirect unauthenticated users before they even reach a page.
- Server Components: Checking for a session directly using
cookies()or a library like Auth.js to conditionally render content. - Route Handlers/Actions: Validating the session before performing any sensitive mutations.
Next.js Caching Mechanisms
Next.js Caching Mechanisms
Next.js provides four distinct caching layers to optimize application performance and reduce costs.
1. Request Memoization
React extends the fetch API to automatically memoize requests with the same URL and options. This lasts for the duration of a single render pass on the server.
2. Data Cache
Stores data across user requests and deployments. It is a persistent cache on the server. You can control this via revalidate or cache: 'force-cache'.
3. Full Route Cache
Next.js automatically caches the rendered output (HTML and RSC payload) of a route at build time or during revalidation. This reduces server work for static routes.
4. Router Cache (Client-side)
An in-memory cache that stores the RSC payload of visited and prefetched segments in the browser, lasting for the duration of a user session.
Next.js Draft Mode
Next.js Draft Mode
Draft Mode allows you to preview content from your Headless CMS in real-time, even if the pages are normally statically generated (SSG).
How it Works
- Enable: You create a Route Handler that calls
draftMode().enable(). This sets a secure cookie in the browser. - Bypass Cache: When the cookie is present, Next.js bypasses the Full Route Cache and the Data Cache for
fetchrequests, ensuring the latest content is fetched from the CMS. - Disable: You can call
draftMode().disable()to clear the cookie and return to normal cached behavior.
Use Case
Content editors want to see how a blog post looks on the live site before hitting “Publish.” Draft Mode enables this without making the site dynamic for all users.
Next.js Error Handling
Next.js Error Handling
Next.js provides a robust error-handling system using special files that allow you to define UI for different error scenarios.
Special Files
error.js: Defines an error boundary for a specific segment and its children. It must be a Client Component.global-error.js: A specialized error boundary for the root layout, used to catch errors in the entire application.not-found.js: Used to render a UI when thenotFound()function is called or when a route doesn’t match.loading.js: While primarily for streaming, it also handles the “loading” state during data fetching.
How it works
When an error occurs in a component, Next.js will bubble it up to the nearest error.js boundary. This allows the rest of the application to remain functional while the specific segment shows a fallback UI.
Next.js Font and Script Optimization
Next.js Font and Script Optimization
Next.js provides built-in components to optimize the loading of fonts and scripts.
Next Font (next/font)
Automatically optimizes your fonts (including custom fonts) and removes external network requests for improved privacy and performance.
- Zero Layout Shift: Automatically calculates the size of the font to prevent CLS.
- Self-hosting: Google Fonts are downloaded at build time and hosted with your deployment.
Next Script (next/script)
The Script component enables you to set the loading priority of third-party scripts.
beforeInteractive: Load before any Next.js code and before page hydration.afterInteractive: (Default) Load immediately after page hydration.lazyOnload: Load during idle time.worker: (Experimental) Load in a web worker.
Forms and Validation
Next.js Forms and Validation
Next.js leverages Server Actions and React’s specialized hooks to provide a seamless form-handling experience.
Key Components
- Server Actions: Handle the backend logic of the form submission.
useActionState(formerlyuseFormState): Manages the state of the form (e.g., success message, validation errors) returned from the action.useFormStatus: Provides thependingstate of the submission for UI feedback (like loading spinners).- Zod: Often used alongside Server Actions to validate
FormDataon the server before processing. - Progressive Enhancement: Forms can work with standard HTML
<form action="...">even before JavaScript has loaded.
Next.js Internationalization (i18n)
Next.js Internationalization (i18n)
Next.js allows you to configure routing and rendering of content to support multiple languages.
Routing Strategy
In the App Router, i18n is typically implemented using dynamic route segments. A common pattern is putting all routes inside a [lang] folder (e.g., app/[lang]/page.tsx).
Key Components
- Middleware: Used to detect the user’s preferred language (via the
Accept-Languageheader or a cookie) and redirect them to the appropriate localized route. - Dictionaries: JSON files containing translations for each language, which are loaded as needed in Server Components.
- Static Generation: Using
generateStaticParamsto pre-render all pages for all supported languages.
Next.js Image Optimization
Next.js Image Optimization
The next/image component extends the HTML <img> element with features to help you achieve good Core Web Vitals, specifically Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS).
Key Features
- Size Optimization: Automatically serves correctly sized images for each device using modern formats like WebP and AVIF.
- Visual Stability: Prevents layout shift automatically by requiring dimensions or using
fill. - Faster Page Loads: Images are only loaded when they enter the viewport using native browser lazy loading, with optional blur-up placeholders.
- Asset Flexibility: On-demand image resizing, even for images stored on remote servers.
Instrumentation and Monitoring
Next.js Instrumentation and Monitoring
Instrumentation is the process of using code to integrate monitoring and logging tools into your application.
The instrumentation.ts File
Next.js provides a special instrumentation.ts file in the root directory (or src/) that runs once when a new Next.js server instance is started. This is the place to:
- Initialize monitoring tools (Sentry, New Relic, etc.).
- Configure OpenTelemetry (OTEL) for distributed tracing.
- Run any necessary side effects on server startup.
OpenTelemetry
Next.js has built-in support for OpenTelemetry, allowing you to export spans and traces to observability platforms. This helps in debugging slow database queries or API calls across different services.
Next.js Metadata API
Next.js Metadata API
The Metadata API allows you to define metadata (e.g. meta and link tags inside your HTML head element) using a declarative object in your layouts or pages.
Key Features
- Static Metadata: Export a
metadataobject from a layout or page. - Dynamic Metadata: Export a
generateMetadatafunction to fetch metadata based on dynamic parameters. - Inheritance: Metadata is automatically merged from parent layouts to child pages, following a specific evaluation order.
- File-based Metadata: Support for special files like
favicon.ico,opengraph-image.png, andsitemap.xml.
Next.js Middleware
Next.js Middleware
Middleware allows you to run code before a request is completed. Based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.
Key Characteristics
- Edge Runtime: Middleware runs on the Edge, making it extremely fast and low-latency.
- Filtering: You can use a
matcherto limit Middleware to specific paths. - Use Cases: Authentication, Bot protection, A/B testing, Redirects, and Localization.
Next.js Rendering Strategies
Next.js Rendering Strategies
Next.js provides several ways to render your content, each with different performance characteristics and use cases.
Static Site Generation (SSG)
Next.js generates the HTML at build time. The pre-rendered HTML is then reused on each request. It can be cached by a CDN.
- Use case: Marketing pages, blog posts, documentation.
Server-Side Rendering (SSR)
Next.js generates the HTML on each request.
- Use case: Pages with highly dynamic data or user-specific content.
Incremental Static Regeneration (ISR)
Enables you to use static generation on a per-page basis without needing to rebuild the entire site.
- Use case: Large scale sites with frequently updated data.
Next.js Route Handlers
Next.js Route Handlers
Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs. They are the App Router’s equivalent of API Routes.
Key Characteristics
- File-based: Defined in
route.tsorroute.jsfiles. - HTTP Methods: Supported methods include
GET,POST,PUT,PATCH,DELETE,HEAD, andOPTIONS. - Edge & Node.js Runtimes: Can run in either runtime, depending on configuration.
- Caching:
GETrequests are cached by default unless they use dynamic functions (likecookies()) or are explicitly opted out. - Conflict: A
route.tsfile cannot exist in the same folder as apage.tsfile.
Next.js Security and Secrets
Next.js Security and Secrets
Next.js provides built-in mechanisms to prevent accidental data leaks and protect your application.
Environment Variables
- Private: Variables in
.envare only available in the Node.js environment (Server Components, Route Handlers). - Public: Variables prefixed with
NEXT_PUBLIC_are bundled into the JavaScript sent to the browser.
Data Tainting (Experimental)
The Taint API (experimental_taintObjectReference and experimental_taintUniqueValue) allows you to mark specific objects or values as “private,” preventing them from being passed to a Client Component.
Server Actions Security
Server Actions are protected from CSRF by default. However, developers must still implement Authorization within the action itself to ensure the current user has permission to perform the task.
Next.js Server Actions
Next.js Server Actions
Server Actions are asynchronous functions that are executed on the server. Introduced in Next.js 13.4 and stabilized in Next.js 14, they can be used in both Server and Client Components to handle form submissions and data mutations in Next.js applications.
Key Benefits
- Zero Client JavaScript: When used with forms, they can work without client-side JS (Progressive Enhancement).
- Reduced Boilerplate: No need to manually create API routes for simple mutations.
- Type Safety: Integrated with TypeScript for end-to-end type safety between the form and the server.
- Cache Integration: Works seamlessly with
revalidatePathandrevalidateTagto update the data cache.
Static vs. Dynamic Rendering
Static vs. Dynamic Rendering
Next.js automatically determines if a route is Static or Dynamic based on the features and data-fetching methods used.
Static Rendering
Next.js renders the route at build time, or in the background after data revalidation. The result is cached and can be pushed to a CDN. This is the default behavior.
Dynamic Rendering
Next.js renders the route for each user at request time. This is necessary when the route has data that is unique to the user or only known at the time of the request (e.g., cookies, URL search parameters).
Switching to Dynamic Rendering
A route will switch to dynamic rendering if:
- Dynamic Functions are used:
cookies(),headers(), orsearchParamsin a page. - Uncached Data Requests are used:
fetchwithcache: 'no-store'orrevalidate: 0. - Segment Config Options are set:
export const dynamic = 'force-dynamic'.
Next.js Streaming and Suspense
Next.js Streaming and Suspense
Streaming allows you to break down the page’s HTML into smaller chunks and progressively send them from the server to the client. This is powered by React Suspense.
Key Benefits
- Faster TTFB (Time to First Byte): The server can start sending the layout and non-dynamic parts of the page immediately while the data-heavy components are still fetching.
- Parallel Data Fetching: Different parts of the page can load independently. A slow API call in one component won’t block the rest of the page from being interactive.
- Improved UX: Instead of a blank screen or a full-page spinner, users see the navigation and layout immediately, with specific loading states (skeletons) where data is missing.
Implementation
loading.js: A special file that automatically wraps a page or segment in a Suspense boundary.- Manual
<Suspense>: For more granular control within a page, wrapping specific components.