The React Server Components architecture, which separates components into Client and Server types, has been integrated with Next.js's App Router. When using the app router, it's crucial to distinguish between server-only and client-side code to ensure application security, performance, and maintainability. This blog post explains how to define server-only code in a Next.js application.
Understanding Server-only code
In Next.js, server-only code refers to code intended to run exclusively on the server. This includes:
- Using server-specific libraries.
- Accessing environment variables with sensitive information.
- Interacting with databases or external APIs.
- Processing confidential business logic.
A challenge arises because JavaScript modules can be shared between server and client components, potentially leading to unintentional inclusion of server-side code in the client bundle. This can expose sensitive data, increase the bundle size, and create security vulnerabilities.
Practical example
Let's go through an example to illustrate server-only code. Start by creating a
Next.js application using create-next-app
. Then, in a new src/utils
directory, add a file named server-utils.ts
with the following server-side
function:
This function uses various NPM packages, accesses API keys, retrieves data from a database, and processes sensitive algorithms, which should never be exposed to the client side.
Implementing Server-only code
Next, use this function in a server component, such as an About page component:
When you navigate to the /about
route, you'll see log messages in the server
terminal, not in the browser, indicating that the code is server-only.
However, if this function is mistakenly imported into a client component, like a Dashboard page, it may not work properly. This is where the server-only package helps.
Using the Server-only package
To protect your application, install the server-only package:
Then, update server-utils.ts
to include this package:
Now, if someone tries to import serverSideFunction
into a client component,
the build process will throw an error, preventing server-side code from leaking
to the client.
Client-only package
Just as server-only code needs isolation, client-only code that interacts with browser-specific features like the DOM, the window object, and localStorage must be confined to the client side. The client-only package ensures that client-side code remains where it belongs.
Conclusion
Maintaining a clear boundary between server-only and client-side code is essential in Next.js applications. It ensures your application's integrity, security, and user experience. Use the server-only and client-only packages and follow best practices to enforce this separation and protect your application.