Learn how to reuse the same function across React client and server (RSC) environments with conditional exports using react-server and server-only. This guide walks you through a real example showing how to safely configure headers and share logic between client and server in TypeScript.
Written by: Chia1104 CC BY-NC-SA 4.0
When developing a personal project, I ran into a situation where I wanted to reuse the same function on both the React client side and the server side (RSC). However, I needed to make slight adjustments depending on the environment. For example, on the server side, I needed to include an additional header containing a client secret for the request.
import "server-only";
import { createAuthClient } from "better-auth/client";
import { X_INTERNAL_REQUEST_SECRET } from "@chia/utils";
import { env } from "./env";
import { baseAuthClient } from "./utils";
export const authClient = createAuthClient(
baseAuthClient({
fetchOptions: {
headers: {
[X_INTERNAL_REQUEST_SECRET]: env.INTERNAL_REQUEST_SECRET ?? "",
},
},
})
);React provides a mechanism for conditional exports based on ES Modules, allowing you to expose different files depending on the execution environment using the react-server condition.
Important: Make sure the default export is declared after the react-server one — otherwise it will be overwritten.
{
"$schema": "https://json.schemastore.org/package",
"name": "@chia/auth",
"version": "0.0.0",
"private": true,
"type": "module",
"exports": {
"./client": {
"types": "./src/client.ts",
"react-server": "./src/client.rsc.ts",
"default": "./src/client.ts"
}
}
}Inside the file, you can also import "server-only" to ensure the method won’t be bundled or executed on the client side.
For more details, refer to React RFC #0277, which describes the react-server conditional export conventions.