Server-Only Module Enforcer for React
The `server-only` package is a fundamental marker utility in the React Server Components (RSC) architecture. Its primary purpose is to enforce that a JavaScript module, and any code within it, can only be executed within a server-side environment. This is crucial for preventing sensitive server-side logic, such as database queries, direct file system access, or API keys, from accidentally being bundled and exposed to the client-side. The package achieves this through a clever use of conditional exports in its `package.json`. In a React Server Component build environment, it resolves to an empty file, effectively doing nothing. However, if imported into a client-side component, it resolves to a file that throws a build-time error, acting as a safeguard against data leaks, increased bundle sizes, and runtime failures. It is maintained by the React team, currently at version `0.0.1`, and its stability reflects its minimalistic and declarative role within the RSC paradigm. It differentiates itself by providing a strict, compile-time guarantee for server-only code separation, complementing newer runtime APIs like `experimental_taintObjectReference` which offer finer-grained control.
Common errors
-
You're importing a component that needs "server-only". This only works in a Server Component environment.
cause A module containing `import 'server-only';` was imported into a file or component that is intended for client-side execution (e.g., a file with `'use client'` directive, or a module that's part of the client bundle).fixReview the import path and ensure the offending import is only used within React Server Components or server-side utility files. If the functionality is needed on the client, it must be rewritten using client-compatible APIs or passed as serializable data from a Server Component.
Warnings
- breaking Attempting to import a module marked with `server-only` into any client-side component or file will result in a build-time error. This is by design to prevent server-side code from leaking to the client.
- gotcha The `server-only` package itself contains very little executable code. Its functionality relies on conditional exports in its `package.json` that cause a build tool (like Next.js's bundler) to throw an error when imported in a client context.
- gotcha While `server-only` marks an entire module as server-exclusive, it does not prevent passing server-only values (like a database client or API key) as props from a Server Component down to a Client Component. Such values must be serializable or explicitly tainted.
Install
-
npm install server-only -
yarn add server-only -
pnpm add server-only
Imports
- Side Effect Import
import { someExport } from 'server-only';import 'server-only';
Quickstart
/* src/lib/server-utils.ts */
// This directive ensures that this entire file can only be imported in Server Components.
import 'server-only';
import { promises as fs } from 'fs';
export async function getSecretData() {
// This code will only run on the server.
// Accessing process.env directly is safe here.
const apiKey = process.env.DATABASE_API_KEY ?? 'default_api_key';
console.log('Fetching secret data on the server...');
// Simulate reading from a server-side file system
const fileContent = await fs.readFile(process.cwd() + '/src/lib/server-config.txt', 'utf-8');
return {
message: `Hello from the server! Key used: ${apiKey.substring(0, 5)}...`,
config: fileContent
};
}
/* src/app/page.tsx (Server Component) */
// This is a Server Component, so it can safely import 'server-utils.ts'
import { getSecretData } from '../lib/server-utils';
export default async function HomePage() {
const data = await getSecretData();
return (
<div>
<h1>Welcome to the Server Component App</h1>
<p>{data.message}</p>
<p>Server config snippet: {data.config.substring(0, 20)}...</p>
{/* You cannot import 'use client' components here that directly use getSecretData */}
</div>
);
}
// Example of how to prevent client-side usage, if you tried to import getSecretData in a 'use client' component:
// /* src/components/ClientComponent.tsx */
// 'use client';
// import { getSecretData } from '../lib/server-utils'; // This line would cause a build error
// export default function ClientComponent() { return <div>Client component</div>; }