server-only Package: Build-Time Client-Leak Prevention
- Last updated
- Prerequisites:
- React Server Components boundary
- Client vs Server modules
- nextjs
- server-only
- security
- rsc
- bundling
- secrets
Read at your depth
The practical view
The `server-only` package prevents server-side code (database clients, API keys, private business logic) from accidentally being imported into Client Components (`'use client'`). You import it once at the top of a server file: `import 'server-only';`. If any Client Component directly or indirectly imports that file, Next.js immediately halts the build with a compilation error.
The same idea in other frameworks
Vite environment conditions or custom Rollup plugin bans on server modules.Angular SSR build isolation preventing server services from leaking to browser bundles.Nuxt `.server.ts` filename convention preventing client bundling.SvelteKit `$env/static/private` and `$env/dynamic/private` compile-time import guards.Legacy vs modern
Accidental secret leak vs Poisoned server-only guard
Transitive imports of server utilities can bundle API secrets to the browser; `server-only` breaks the build before deployment.
export const db = new DatabaseClient(process.env.DB_SECRET); // ❌ Dangerous if imported in clientimport 'server-only'; // ✅ NEW: Fails build if imported by client componentInterview gotchas
Context
Interviewers want to see if you understand Node/bundler package conditional exports.
The mechanical answer
`server-only` relies on the Node.js `package.json` `exports` field. For the `react-server` export condition (used when bundling Server Components), it resolves to an empty file `empty.js`. For all other conditions (including `browser` and standard client bundling), it resolves to an `index.js` that throws a fatal error during bundling.
Trap
Do not answer that `server-only` runs an `if (typeof window !== 'undefined')` check at runtime. It enforces safety at *build time*.
Context
This tests knowledge of the symmetric RSC isolation tooling.
The mechanical answer
`client-only` is the counterpart package. Adding `import 'client-only';` at the top of a file ensures it can only be imported in Client Components. If a Server Component imports it, the build fails (preventing server execution of window/DOM-dependent code).
Trap
Remember that neither `server-only` nor `client-only` replace the `'use client'` or `'use server'` directives; they are runtime-guard assertions, not boundary declarations.