Server-Only Module Enforcer for React

0.0.1 · active · verified Sun Apr 19

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

Warnings

Install

Imports

Quickstart

Demonstrates marking a utility file as server-only and its safe usage within a React Server Component, illustrating how to prevent accidental client-side imports.

/* 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>; }

view raw JSON →