NextJS/React Flashcards
studying nextjs react docs
What is the React Server Component Payload (RSC)?
The RSC Payload is a compact binary representation of the rendered React Server Components tree. It’s used by React on the client to update the browser’s DOM. The RSC Payload contains:
- The rendered result of Server Components
- Placeholders for where Client Components should be rendered and references to their JavaScript files
- Any props passed from a Server Component to a Client Component
What are three different server rendering strategies for Server Components?
- Static Rendering
- Dynamic Rendering
- Streaming
What are the benefits of Server side Rendering?
- Security
- Caching
- Performance
- Initial Page Load
- SEO
- Streaming
How are Server Components rendered?
What is Static Rendering (Default)
With Static Rendering, routes are rendered at build time, or in the background after data revalidation. The result is cached and can be pushed to a Content Delivery Network (CDN). This optimization allows you to share the result of the rendering work between users and server requests.
Static rendering is useful when a route has data that is not personalized to the user and can be known at build time, such as a static blog post or a product page.
How does Server Dynamic Rendering work?
With Dynamic Rendering, routes are rendered for each user at request time.
Dynamic rendering is useful when a route has data that is personalized to the user or has information that can only be known at request time, such as cookies or the URL’s search params.
Dynamic Routes with Cached Data
In most websites, routes are not fully static or fully dynamic - it’s a spectrum. For example, you can have an e-commerce page that uses cached product data that’s revalidated at an interval, but also has uncached, personalized customer data.
In Next.js, you can have dynamically rendered routes that have both cached and uncached data. This is because the RSC Payload and data are cached separately. This allows you to opt into dynamic rendering without worrying about the performance impact of fetching all the data at request time.
What happens if, during rendering, NextJS discovers a dynamic function or an uncached data request?
During rendering, NextJS will switch to dynamically rendering the whole route. This table summarizes how dynamic functions and data caching affect whether a route is statically or dynamically rendered
In the table above, for a route to be fully static, all data must be cached. However, you can have a dynamically rendered route that uses both cached and uncached data fetches.
As a developer, do you need to choose between static and dynamic rendering in NextJS?
No, NextJS will decide this for you. NextJS will automatically choose the best rendering strategy for each route based on the features and APIs used.
However, you do need to choose when to cache or revalidate specific data, and you may choose to stream parts of your UI.
What are dynamic functions?
Dynamic functions rely on information that can only be known at request time such as a user’s cookies, current requests headers, or the URL’s search params. In Next.js, these dynamic functions are:
-
cookies()
andheaders():
Using these in a Server Component will opt the whole route into dynamic rendering at request time. - searchParams: Using the Pages prop will opt the page into dynamic rendering at request time.
Using any of these functions will opt the whole route into dynamic rendering at request time.
How does Streaming server rendering work?
Streaming enables you to progressively render UI from the server. Work is split into chunks and streamed to the client as it becomes ready. This allows the user to see parts of the page immediately, before the entire content has finished rendering.
- built into App Router by default
What are Client Components in NextJS?
Client Components allow you to write interactive UI that is prerendered on the server and can use client JavaScript to run in the browser.
What are the benefits of Client Rendering?
How do you use Client Components in Next.js?
To use Client Components, you can add the React “use client” directive at the top of a file, above your imports.
“use client” is used to declare a boundary between a Server and Client Component modules. This means that by defining a “use client” in a file, all other modules imported into it, including child components, are considered part of the client bundle.
Can you define multiple “use client” entry points?
Yes, you can define multiple “use client” entry points in your React Component tree. This allows you to split your application into multiple client bundles.
However, “use client” doesn’t need to be defined in every component that needs to be rendered on the client. Once you define the boundary, all child components and modules imported into it are considered part of the client bundle.
The diagram below shows that using onClick and useState in a nested component (toggle.js) will cause an error if the “use client” directive is not defined. This is because, by default, all components in the App Router are Server Components where these APIs are not available. By defining the “use client” directive in toggle.js, you can tell React to enter the client boundary where these APIs are available.
How are Client Components Rendered?
In Next.js, Client Components are rendered differently depending on whether the request is part of a full page load (an initial visit to your application or a page reload triggered by a browser refresh) or a subsequent navigation.
How are Client Components Rendered on Full page load?
To optimize the initial page load, Next.js will use React’s APIs to render a static HTML preview on the server for both Client and Server Components. This means, when the user first visits your application, they will see the content of the page immediately, without having to wait for the client to download, parse, and execute the Client Component JavaScript bundle.
On the server:
- React renders Server Components into a special data format called the React Server Component Payload (RSC Payload), which includes references to Client Components.
- Next.js uses the RSC Payload and Client Component JavaScript instructions to render HTML for the route on the server.
Then, on the client:
- The HTML is used to immediately show a fast non-interactive initial preview of the route.
- The React Server Components Payload is used to reconcile the Client and Server Component trees, and update the DOM.
- The JavaScript instructions are used to hydrate Client Components and make their UI interactive.
What is hydration?
Hydration is the process of attaching event listeners to the DOM, to make the static HTML interactive. Behind the scenes, hydration is done with the hydrateRoot React API.
How are Client Components Rendered on Subsequent Navigations?
On subsequent navigations, Client Components are rendered entirely on the client, without the server-rendered HTML.
This means the Client Component JavaScript bundle is downloaded and parsed. Once the bundle is ready, React will use the RSC Payload to reconcile the Client and Server Component trees, and update the DOM.
When to use Server and Client Components?
What are some common patterns for working with Server Components?
- Sharing data between components
- Keeping Server-only code out of the Client Environment
- Using Third-party Packages and Providers
- Using Context Providers
What are some common patterns for working with Client Components?
- Moving Client Components Down the Tree
- Serialization - passing props from Server to Client Components
- Interleaving Server and Client Components
- anti pattern: importing server comps into client comps
- supported pattern: passing Server Comps to Client Components as props
Explain the Server Component pattern where you Share data between components.
When fetching data on the server, there may be cases where you need to share data across different components. For example, you may have a layout and a page that depend on the same data.
Instead of using React Context (which is not available on the server) or passing data as props, you can use fetch or React’s cache function to fetch the same data in the components that need it, without worrying about making duplicate requests for the same data. This is because React extends fetch to automatically memoize data requests, and the cache function can be used when fetch is not available.
Explain the Server Component pattern: Keeping Server-only Code out of the Client Environment
To prevent this sort of unintended client usage of server code, we can use the server-only
package to give other developers a build-time error if they ever accidentally import one of these modules into a Client Component.
To use server-only, first install the package:
Then import the package into any module that contains server-only code:
Now, any Client Component that imports getData() will receive a build-time error explaining that this module can only be used on the server.
The corresponding package client-only can be used to mark modules that contain client-only code – for example, code that accesses the window object.
Explain the Server Component pattern for using third-party packages and providers.
Since Server Components are a new React feature, third-party packages and providers don’t yet have the “use client” directive, and so won’t work in Server Components.
The Solution is wrap third-party components that rely on client-only features in your own Client Components.
You won’t need to do this for every component, but you do need to for providers b/c they reply on React state and context and are typically needed at the root of the application.
How can you use Context Providers with Server Components? (React context is not supported in SCs)
create context in a Client Component using “use client” and then import it into a Server Component.
Good to know: You should render providers as deep as possible in the tree – notice how ThemeProvider only wraps {children} instead of the entire <html> document. This makes it easier for Next.js to optimize the static parts of your Server Components.
Explain the Client Component pattern:
Moving Client Components Down the Tree.
To reduce the Client JavaScript bundle size, we recommend moving Client Components down your component tree.
For example, you may have a Layout that has static elements (e.g. logo, links, etc) and an interactive search bar that uses state.
Instead of making the whole layout a Client Component, move the interactive logic to a Client Component (e.g. <SearchBar></SearchBar>) and keep your layout as a Server Component. This means you don’t have to send all the component Javascript of the layout to the client.
Explain the Client Component pattern:
Passing props from Server to Client Components (Serialization)
If you fetch data in a Server Component, you may want to pass data down as props to Client Components. Props passed from the Server to Client Components need to be serializable by React.
If your Client Components depend on data that is not serializable, you can fetch data on the client with a third party library or on the server via a Route Handler.
Explain the Client Component pattern:
Interleaving Server and Client Components.
When interleaving Client and Server Components, it may be helpful to visualize your UI as a tree of components. Starting with the root layout, which is a Server Component, you can then render certain subtrees of components on the client by adding the “use client” directive.
Within those client subtrees, you can still nest Server Components or call Server Actions, however there are some things to keep in mind:
- During a request-response lifecycle, your code moves from the server to the client. If you need to access data or resources on the server while on the client, you’ll be making a new request to the server - not switching back and forth.
- When a new request is made to the server, all Server Components are rendered first, including those nested inside Client Components. The rendered result (RSC Payload) will contain references to the locations of Client Components. Then, on the client, React uses the RSC Payload to reconcile Server and Client Components into a single tree.
- Since Client Components are rendered after Server Components, you cannot import a Server Component into a Client Component module (since it would require a new request back to the server). Instead, you can pass a Server Component as props to a Client Component. See the unsupported pattern and supported pattern sections below.
Unsupported Pattern: Importing Server Components into Client Components - what does it look like?
Supported Pattern: Passing Server Components to Client Components as Props - what does it look like?
The following pattern is supported. You can pass Server Components as a prop to a Client Component.
A common pattern is to use the React children prop to create a “slot” in your Client Component.
With this approach, <ClientComponent> and <ServerComponent> are decoupled and can be rendered independently. In this case, the child <ServerComponent> can be rendered on the server, well before <ClientComponent> is rendered on the client.</ClientComponent></ServerComponent></ServerComponent></ClientComponent>
Good to know:
- The pattern of “lifting content up” has been used to avoid re-rendering a nested child component when a parent component re-renders.
- You’re not limited to the children prop. You can use any prop to pass JSX.
What are runtimes in the context of Next.js
In the context of Next.js, runtime refers to the set of libraries, APIs, and general functionality available to your code during execution.
On the server, there are two runtimes where parts of your application code can be rendered:
- The Node.js Runtime (default) has access to all Node.js APIs and compatible packages from the ecosystem.
- The Edge Runtime is based on Web APIs.
What are the differences to consider when choosing a runtime in NextJS?
What is the Edge Runtime in NextJS and when should you use it?
In Next.js, the lightweight Edge Runtime is a subset of available Node.js APIs.
The Edge Runtime is ideal if you need to deliver dynamic, personalized content at low latency with small, simple functions. The Edge Runtime’s speed comes from its minimal use of resources, but that can be limiting in many scenarios.
For example, code executed in the Edge Runtime on Vercel cannot exceed between 1 MB and 4 MB, this limit includes imported packages, fonts and files, and will vary depending on your deployment infrastructure. In addition, the Edge Runtime does not support all Node.js APIs meaning some npm packages may not work. For example, “Module not found: Can’t resolve ‘fs’” or similar errors. We recommend using the Node.js runtime if you need to use these APIs or packages.
What is the Node.js Runtime in NextJS and when should you use it?
Using the Node.js runtime gives you access to all Node.js APIs, and all npm packages that rely on them. However, it’s not as fast to start up as routes using the Edge runtime.
Deploying your Next.js application to a Node.js server will require managing, scaling, and configuring your infrastructure. Alternatively, you can consider deploying your Next.js application to a serverless platform like Vercel, which will handle this for you.
When should you use Serverless Node.js? What are the downsides to using it?
Serverless is ideal if you need a scalable solution that can handle more complex computational loads than the Edge Runtime. With Serverless Functions on Vercel, for example, your overall code size is 50MB including imported packages, fonts, and files.
The downside compared to routes using the Edge is that it can take hundreds of milliseconds for Serverless Functions to boot up before they begin processing requests. Depending on the amount of traffic your site receives, this could be a frequent occurrence as the functions are not frequently “warm”.
With SSR (Server Side Rendering), what are the series of steps that need to be completed before a user can see and interact with a page?
- First, all data for a given page is fetched on the server.
- The server then renders the HTML for the page.
- The HTML, CSS, and JavaScript for the page are sent to the client.
- A non-interactive user interface is shown using the generated HTML, and CSS.
- Finally, React hydrates the user interface to make it interactive.
These steps are sequential and blocking, meaning the server can only render the HTML for a page once all the data has been fetched. And, on the client, React can only hydrate the UI once the code for all components in the page has been downloaded.
How does SSR help improve the perceived loading performance? What are the limitations?
By showing a non-interactive page to the user as soon as possible.
However, it can still be slow as all data fetching on server needs to be completed before the page can be shown to the user.
What are the benefits of Streaming rendering?
Streaming allows you to break down the page’s HTML into smaller chunks and progressively send those chunks from the server to the client.
This enables parts of the page to be displayed sooner, without waiting for all the data to load before any UI can be rendered.
Streaming works well with React’s component model because each component can be considered a chunk.
Components that have higher priority (e.g. product information) or that don’t rely on data can be sent first (e.g. layout), and React can start hydration earlier.
Components that have lower priority (e.g. reviews, related products) can be sent in the same server request after their data has been fetched.
Streaming is particularly beneficial when you want to prevent long data requests from blocking the page from rendering as it can reduce the Time To First Byte (TTFB) and First Contentful Paint (FCP). It also helps improve Time to Interactive (TTI), especially on slower devices.
What is Time to First Byte (TTFB)?
Time to First Byte (TTFB) is a foundational metric for measuring connection setup time and web server responsiveness in both the lab and the field. It measures the time between the request for a resource and when the first byte of a response begins to arrive. This makes it helpful in identifying when a web server is too slow to respond to requests. In the case of navigation requests—that is, requests for an HTML document—it precedes every other meaningful loading performance metric.
TTFB is the sum of the following request phases:
- Redirect time
- Service worker startup time (if applicable)
- DNS lookup
- Connection and TLS negotiation
Request, until the first byte of the response arrives - Reducing latency in connection setup time and on the backend helps lower your TTFB.
What is a good TTFB score?
As a rough guide, most sites should strive to have a TTFB of 0.8 seconds or less.
Because TTFB happens before user-centric metrics such as First Contentful Paint (FCP) and Largest Contentful Paint (LCP), we recommend that your server respond to navigation requests quickly enough so that the 75th percentile of users experience an FCP within the “good” threshold.
Key point: Because TTFB isn’t a Core Web Vitals metric, it’s not absolutely necessary for sites to have an excellent TTFB, as long as the longer TTFB doesn’t make it harder for your site to score well on the metrics that matter. When optimizing load times, consider how your site delivers content. A low TTFB is especially important if a site delivers its initial markup quickly and then has to wait for scripts to populate it with meaningful content, as is often the case with Single Page Applications (SPAs). On the other hand, a server-rendered site that doesn’t require much client-side work can have better FCP and LCP values than a client-rendered site, even if its TTFB is higher.
What is First Contentful Paint? (FCP)
First Contentful Paint (FCP) is one of six metrics tracked in the Performance section of the Lighthouse report. Each metric captures some aspect of page load speed.
FCP measures how long it takes the browser to render the first piece of DOM content after a user navigates to your page. Images, non-white <canvas> elements, and SVGs on your page are considered DOM content; anything inside an iframe isn't included.</canvas>
What is Time to Interactive (TTI)? Why is it important to measure?
TTI measures how long it takes a page to become fully interactive. A page is considered fully interactive when:
- The page displays useful content, which is measured by the First Contentful Paint,
- Event handlers are registered for most visible page elements, and
- The page responds to user interactions within 50 milliseconds.
Measuring TTI is important because some sites optimize content visibility at the expense of interactivity. This can create a frustrating user experience: the site appears to be ready, but when the user tries to interact with it, nothing happens.
sites performing in the ninety-ninth percentile render TTI in about 2.2 seconds. If your website’s TTI is 2.2 seconds, your TTI score is 99.
How do you improve your TTI score?
One improvement that can have a particularly big effect on TTI is deferring or removing unnecessary JavaScript work. Look for opportunities to optimize your JavaScript. In particular, consider reducing JavaScript payloads with code splitting and applying the PRPL pattern. Optimizing third-party JavaScript also yields significant improvements for some sites.
These two Diagnostic audits provide additional opportunities to reduce JavaScript work:
- Minimize main thread work
- Reduce JavaScript execution time
How does the Suspense component work? what are the benefits?
<Suspense> works by wrapping a component that performs an asynchronous action (e.g. fetch data), showing fallback UI (e.g. skeleton, spinner) while it's happening, and then swapping in your component once the action completes.
By using Suspense, you get the benefits of:
1. Streaming Server Rendering - Progressively rendering HTML from the server to the client.
2.Selective Hydration - React prioritizes what components to make interactive first based on user interaction.
![!BS! ](https://s3.amazonaws.com/brainscape-prod/system/cm/496/795/492/a_image_ios.?1711570937 "eyJvcmlnaW5hbFVybCI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9icmFpbnNjYXBlLXByb2Qvc3lzdGVtL2NtLzQ5Ni83OTUvNDkyL2FfaW1hZ2Vfb3JpZ2luYWwuP2YxZTkyYjc2NDE2MmQxZGY3OTVmNjNmN2RmNDk5Y2RhIn0=")
</Suspense>
How does Streaming with Suspense interact with SEO?
- Next.js will wait for data fetching inside
generateMetadata
to complete before streaming UI to the client. This guarantees the first part of a streamed response includes <head> tags. - Since streaming is server-rendered, it does not impact SEO. You can use the Rich Results Test tool from Google to see how your page appears to Google’s web crawlers and view the serialized HTML (source).
How do Status Codes work when Streaming w/ Suspense?
When streaming, a 200 status code will be returned to signal that the request was successful.
The server can still communicate errors or issues to the client within the streamed content itself, for example, when using redirect
or notFound
. Since the response headers have already been sent to the client, the status code of the response cannot be updated. This does not affect SEO.
What are Server Actions? How do you use them?
Server Actions are asynchronous functions that are executed on the server. They can be used in Server and Client Components to handle form submissions and data mutations in Next.js applications.
A Server Action can be defined with the React “use server” directive. You can place the directive at the top of an async function to mark the function as a Server Action, or at the top of a separate file to mark all exports of that file as Server Actions.
How do you use a Server Action in a Server Component?
Server Components can use the inline function level or module level “use server” directive. To inline a Server Action, add “use server” to the top of the function body:
How do you use Server Actions in a Client Component?
Client Components can only import actions that use the module-level “use server” directive.
To call a Server Action in a Client Component, create a new file and add the “use server” directive at the top of it. All functions within the file will be marked as Server Actions that can be reused in both Client and Server Components:
Can you pass a Server Action to a Client Component as a prop? How?
How do you invoke a Server Action? Describe the behavior.
What does it mean that Server Components support progressive enhancement by default?
Server Components support progressive enhancement by default, meaning the form will be submitted even if JavaScript hasn’t loaded yet or is disabled.
Are Server Actions limited to <form> elements?
No, Server Actions are not limited to <form> and can be invoked from event handlers, useEffect, third-party libraries, and other form elements like <button>.</button>
Which part of the NextJS architecture do Server Actions interact with?
Server Actions integrate with the Next.js caching and revalidation architecture. When an action is invoked, Next.js can return both the updated UI and new data in a single server roundtrip.
True or False: actions can use multiple types of HTTP methods.
False. Behind the scenes, actions use the POST method, and only this HTTP method can invoke them.
What does React require of args and return values for Server Actions?
The arguments and return value of Server Actions must be serializable by React. See the React docs for a list of serializable arguments and values.
What does it mean that “Server Actions are functions”?
Server Actions are functions. This means they can be reused anywhere in your application.
What runtime do Server Actions use?
Server Actions inherit the runtime from the page or layout they are used on.
Where do Server Actions get their Route Segment Config?
Server Actions inherit the Route Segment Config from the page or layout they are used on, including fields like maxDuration.
What happens when Server Actions are invoked in a <form>?
React extends the HTML <form> element to allow Server Actions to be invoked with the action prop.
When invoked in a form, the action automatically receives the FormData object. You don’t need to use React useState to manage fields, instead, you can extract the data using the native FormData methods:
Good to know:
- Example: Form with Loading & Error States
- When working with forms that have many fields, you may want to consider using the
entries()
method with JavaScript’sObject.fromEntries()
.
For example: const rawFormData = Object.fromEntries(formData). One thing to note is that the formData
will include additional $ACTION
_ properties.
- See React <form> documentation to learn more.
How do you pass additional arguments to Server Actions in a form?
You can pass additional arguments to a Server Action using the JavaScript bind method.
How do you handle pending states in forms using Server Actions?
You can use the React useFormStatus
hook to show a pending state while the form is being submitted.
Can you use useFormStatus
in a Server Component?
No, useFormStatus
is a React hook and therefore must be used in a Client Component.
How do Server Actions allow you to do server-side validation and error handling with forms?
We recommend using HTML validation like required and type=”email” for basic client-side form validation.
For more advanced server-side validation, you can use a library like zod to validate the form fields before mutating the data. <see></see>
Once the fields have been validated on the server, you can return a serializable object in your action and use the React useFormState
hook to show a message to the user.
By passing the action to useFormState
, the action’s function signature changes to receive a new prevState
or initialState
parameter as its first argument.useFormState
is a React hook and therefore must be used in a Client Component.
What does the React useOptimistic
hook do?
You can use the React useOptimistic
hook to optimistically update the UI before the Server Action finishes, rather than waiting for the response:
Can you invoke Server Actions in elements nested in forms? If so, why would you want to?
You can invoke a Server Action in elements nested inside <form> such as <button>, <input></input>, and <input></input>. These elements accept the formAction prop or event handlers.</button>
This is useful in cases where you want to call multiple server actions within a form. For example, you can create a specific <button> element for saving a post draft in addition to publishing it. See the React <form> docs for more information.</button>
What is programmatic form submission? When and how do you use it?
You can trigger a form submission using the requestSubmit()
method. For example, when the user presses ⌘ + Enter, you can listen for the onKeyDown event:
This will trigger the submission of the nearest <form> ancestor, which will invoke the Server Action.
Aside from forms, where else are Server Actions commonly invoked?
they can also be invoked from other parts of your code such as event handlers and useEffect.
What do you need to consider when invoking Server Actions in Event Handlers? Give an example.
You can invoke a Server Action from event handlers such as onClick
. For example, to increment a like count:
To improve the user experience, we recommend using other React APIs like useOptimistic
and useTransition
to update the UI before the Server Action finishes executing on the server, or to show a pending state.
For cases like onChange
in a form field, where multiple events might be fired in quick succession, we recommend debouncing to prevent unnecessary Server Action invocations.
How do you use the useEffect
hook to invoke a Server Action? When might this be useful?
You can use the React useEffect
hook to invoke a Server Action when the component mounts or a dependency changes.
This is useful for mutations that depend on global events or need to be triggered automatically.
For example, onKeyDown
for app shortcuts, an intersection observer hook for infinite scrolling, or when the component mounts to update a view count:
How do Server Actions handle errors?
When an error is thrown, it’ll be caught by the nearest error.js or <Suspense> boundary on the client. We recommend using try/catch to return errors to be handled by your UI.</Suspense>
For example, your Server Action might handle errors from creating a new item by returning a message:
Good to know:
Aside from throwing the error, you can also return an object to be handled by useFormState. See Server-side validation and error handling.
How do you revalidate data in the Next.js Cache inside of Server Actions?
You can revalidate the Next.js Cache inside your Server Actions with the revalidatePath
API Or invalidate a specific data fetch with a cache tag using revalidateTag
:
How do Server Actions handle redirects?
If you would like to redirect the user to a different route after the completion of a Server Action, you can use redirect
API.
redirect
needs to be called outside of the try/catch
block:
Do Server Actions interact with Cookies? If so, how?
You can get
, set
, and delete
cookies inside a Server Action using the cookies
API:
In the context of Authentication and authorization, how should you treat Server Actions?
You should treat Server Actions as you would public-facing API endpoints, and ensure that the user is authorized to perform the action. For example:
When does defining a Server Action create a closure?
Defining a Server Action inside a component creates a closure where the action has access to the outer function’s scope. For example, the publish action has access to the publishVersion variable.
Closures are useful when you need to capture a snapshot of data (e.g. publishVersion) at the time of rendering so that it can be used later when the action is invoked.
However, for this to happen, the captured variables are sent to the client and back to the server when the action is invoked. Next.js automatically encrypts these variables to prevent data exposure.
What do you need to be aware of when self-hosting your Next.js application across multiple servers?
Overwriting encryption keys (advanced).
When self-hosting your Next.js application across multiple servers, each server instance may end up with a different encryption key, leading to potential inconsistencies.
To mitigate this, you can overwrite the encryption key using the process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
environment variable. Specifying this variable ensures that your encryption keys are persistent across builds, and all server instances use the same key.
This is an advanced use case where consistent encryption behavior across multiple deployments is critical for your application. You should consider standard security practices such key rotation and signing.
Good to know: Next.js applications deployed to Vercel automatically handle this.
What does Next.js do to prevent sensitive data from getting sent to the client in the case of Server Action closures? What are the implications of this?
To prevent sensitive data from being exposed to the client, Next.js automatically encrypts the closed-over variables.
A new private key is generated for each action every time a Next.js application is built. This means actions can only be invoked for a specific build.
How are Server Actions protected from CSRF attacks?
Behind the scenes, Server Actions use the POST method, and only this HTTP method is allowed to invoke them. This prevents most CSRF vulnerabilities in modern browsers, particularly with SameSite cookies being the default.
As an additional protection, Server Actions in Next.js also compare the Origin header to the Host header (or X-Forwarded-Host). If these don’t match, the request will be aborted. In other words, Server Actions can only be invoked on the same host as the page that hosts it.
NOTE: For large applications that use reverse proxies or multi-layered backend architectures (where the server API differs from the production domain), it’s recommended to use the configuration option serverActions.allowedOrigins
option to specify a list of safe origins. The option accepts an array of strings.
What is the best practice for fetching data on the server w/ Next.js? Why - what are the benefits?
Whenever possible, we recommend fetching data on the server with Server Components.
What is the pattern for only fetching data when it’s needed?
If you need to use the same data (e.g. current user) in multiple components in a tree, you do not have to fetch data globally, nor forward props between components. Instead, you can use fetch
or React cache
in the component that needs the data without worrying about the performance implications of making multiple requests for the same data.
This is possible because fetch
requests are automatically memoized. Learn more about request memoization.
Good to know: This also applies to layouts, since it’s not possible to pass data between a parent layout and its children.
What are the two data fetching patterns inside React components?
When fetching data inside React components, you need to be aware of two data fetching patterns: Parallel and Sequential.
- With
sequential data fetching
, requests in a route are dependent on each other and therefore create waterfalls. There may be cases where you want this pattern because one fetch depends on the result of the other, or you want a condition to be satisfied before the next fetch to save resources. However, this behavior can also be unintentional and lead to longer loading times. - With
parallel data fetching
, requests in a route are eagerly initiated and will load data at the same time. This reduces client-server waterfalls and the total time it takes to load data.
What is “all or nothing” data fetching?
An alternative approach to prevent waterfalls is to fetch data globally, at the root of your application, but this will block rendering for all route segments beneath it until the data has finished loading. This can be described as “all or nothing” data fetching. Either you have the entire data for your page or application, or none.
What happens to fetch requests that use await? What should you be aware of?
Any fetch requests with await will block rendering and data fetching for the entire tree beneath it, unless they are wrapped in a <Suspense> boundary or loading.js is used. Another alternative is to use parallel data fetching or the preload pattern.</Suspense>
What is the Parallel Data Fetching pattern?
To fetch data in parallel, you can eagerly initiate requests by defining them outside the components that use the data, then calling them from inside the component. This saves time by initiating both requests in parallel, however, the user won’t see the rendered result until both promises are resolved.
To improve the user experience, you can add a Suspense Boundary to break up the rendering work and show part of the result as soon as possible.
How does the pre-loading data pattern work? What is it used for?
The pre-loading pattern is used to prevent waterfalls. You can optionally create a preload
function to further optimize parallel data fetching.
With this approach, you don’t have to pass promises down as props.
The preload function can also have any name as it’s a pattern, not an API.
What are the benefits of using React cache
, server-only
, and the Preload Pattern?
You can combine the cache
function, the preload pattern, and the server-only
package to create a data fetching utility that can be used throughout your app.
With this approach, you can eagerly fetch data, cache responses, and guarantee that this data fetching only happens on the server.
The utils/get-item exports can be used by Layouts, Pages, or other components to give them control over when an item’s data is fetched.
Good to know:
We recommend using the server-only
package to make sure server data fetching functions are never used on the client.
How can you prevent sensitive data from being exposed to the client?
We recommend using React’s taint APIs, taintObjectReference
and taintUniqueValue
, to prevent whole object instances or sensitive values from being passed to the client.
To enable tainting in your application, set the Next.js Config experimental.taint option to true.
Then pass the object or value you want to taint to the experimental_taintObjectReference or experimental_taintUniqueValue functions:
What are four ways of fetching data with Next.js and React?
- On the server, with fetch
- On the server, with third-party libraries
- On the client, via a Route Handler
- On the client, with third-party libraries.
How do you fetch data on the Server using fetch
? what does this allow you to do?
Next.js extends the native fetch Web API to allow you to configure the caching and revalidating behavior for each fetch request on the server. React extends fetch to automatically memoize fetch requests while rendering a React component tree.
You can use fetch with async/await in Server Components, in Route Handlers, and in Server Actions.
When are fetch
requests NOT memoized?
In Route handlers, fetch requests are not memoized as Route Handlers are not part of the React component tree.
When are fetch
requests NOT cached?
In Server Actions, fetch requests are not cached (defaults cache: no-store).
What is a side effect of using Next.js cookies
and header
functions inside of Server Components?
Next.js provides helpful functions you may need when fetching data in Server Components such as cookies and headers.
These will cause the route to be dynamically rendered as they rely on request time information.
What is Next.js’s default caching behavior?
By default, Next.js automatically caches the returned values of fetch in the Data Cache on the server. This means that the data can be fetched at build time or request time, cached, and reused on each data request.
However, there are exceptions, fetch requests are not cached when:
- Used inside a Server Action.
- Used inside a Route Handler that uses the POST method.
What is the Data Cache?
The Data Cache is a persistent HTTP cache. Depending on your platform, the cache can scale automatically and be shared across multiple regions.
Learn more about the Data Cache.
What is the process of Revalidating Data in relation to caching?
Revalidation is the process of purging the Data Cache and re-fetching the latest data. This is useful when your data changes and you want to ensure you show the latest information.
What are the two ways cached data can be revalidated?
- Time-based revalidation
- On-demand revalidation
What is Time-based revalidation? When is it useful?
Automatically revalidate data after a certain amount of time has passed.
This is useful for data that changes infrequently and freshness is not as critical.
What is On-demand revalidation? When is it useful?
Manually revalidate data based on an event (e.g. form submission). On-demand revalidation can use a tag-based or path-based approach to revalidate groups of data at once.
This is useful when you want to ensure the latest data is shown as soon as possible (e.g. when content from your headless CMS is updated).
How do you implement Time-based revalidation?
To revalidate data at a timed interval, you can use the next.revalidate
option of fetch
to set the cache lifetime of a resource (in seconds).
Alternatively, to revalidate all fetch requests in a route segment, you can use the Segment Config Options.
If you have multiple fetch requests in a statically rendered route, and each has a different revalidation frequency. The lowest time will be used for all requests. For dynamically rendered routes, each fetch request will be revalidated independently.
In the context of time-based data revalidation, how do multiple fetch requests get handled differently by static vs dynamically rendered routes?
In a statically rendered route, and each has a different revalidation frequency. The lowest time will be used for all requests.
For dynamically rendered routes, each fetch request will be revalidated independently.
How do you implement On-demand Revalidation?
Data can be revalidated on-demand by path (revalidatePath
) or by cache tag (revalidateTag
) inside a Server Action or Route Handler.
Next.js has a cache tagging system for invalidating fetch requests across routes.
- When using
fetch
, you have the option to tag cache entries with one or more tags. - Then, you can call
revalidateTag
to revalidate all entries associated with that tag.
What happens when an error gets thrown when you are attempting to revalidate data?
If an error is thrown while attempting to revalidate data, the last successfully generated data will continue to be served from the cache. On the next subsequent request, Next.js will retry revalidating the data.
When are fetch
requests not cached?
How can you opt out of caching for individual fetch
requests?
To opt out of caching for individual fetch requests, you can set the cache option in fetch to ‘no-store’. This will fetch data dynamically, on every request.
How can you opt out of caching for multiple fetch
requests?
If you have multiple fetch
requests in a route segment (e.g. a Layout or Page), you can configure the caching behavior of all data requests in the segment using the Segment Config Options.
However, we recommend configuring the caching behavior of each fetch
request individually. This gives you more granular control over the caching behavior.
What should you remember about Fetching data on the Server with third-party libraries?
In cases where you’re using a third-party library that doesn’t support or expose fetch (for example, a database, CMS, or ORM client), you can configure the caching and revalidating behavior of those requests using the Route Segment Config Option and React’s cache
function.
Whether the data is cached or not will depend on whether the route segment is statically or dynamically rendered.
If the segment is static (default), the output of the request will be cached and revalidated as part of the route segment.
If the segment is dynamic, the output of the request will not be cached and will be re-fetched on every request when the segment is rendered.
What if you need to fetch data in a client component? What do you use? Why might you want to do this?
If you need to fetch data in a client component, you can call a Route Handler from the client.
Route Handlers execute on the server and return the data to the client.
This is useful when you don’t want to expose sensitive information to the client, such as API tokens.
Do Server Components ever need the Route Handler to fetch data?
Since Server Components render on the server, you don’t need to call a Route Handler from a Server Component to fetch data. Instead, you can fetch the data directly inside the Server Component.
Can you fetch data on the Client with third party libraries? When would you want to do this?
You can also fetch data on the client using a third-party library such as SWR or TanStack Query. These libraries provide their own APIs for memoizing requests, caching, revalidating, and mutating data.
Should you ever wrap fetch
in use
in Client Components? why or why not?
use is a React function that accepts and handles a promise returned by a function.
Wrapping fetch
in use
is currently not recommended in Client Components and may trigger multiple re-renders.
Learn more about use in the React docs.
What does the Tree refer to?
A convention for visualizing a hierarchical structure. For example, a component tree with parent and children components, a folder structure, etc.
What is a Subtree?
Part of a tree, starting at a new root (first) and ending at the leaves (last).
What is the Root?
Root: The first node in a tree or subtree, such as a root layout.
What is a Leaf?
Nodes in a subtree that have no children, such as the last segment in a URL path.
What is a URL Segment?
Part of the URL path delimited by slashes.
What is the URL Path?
Part of the URL that comes after the domain (composed of segments).
What is the app Router? Where does it live?
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.
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.
NOTE: app router takes priority over old pages router, incremental switch over allowed
What are the roles of Folders and Files in the Next.js file-system based router?
- 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.
What are Route Segments?
Each folder in a route represents a route segment. Each route segment is mapped to a corresponding segment in a URL path.
How do you create a nested route?
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)