|
| 1 | +--- |
| 2 | +id: environment-functions |
| 3 | +title: Environment Functions |
| 4 | +--- |
| 5 | + |
| 6 | +## What Are Environment Functions? |
| 7 | + |
| 8 | +Environment functions are utilities designed to define and control function execution based on the runtime environment—whether the code is running on the client or the server. These utilities help ensure that environment-specific logic is executed safely and intentionally, preventing runtime errors and improving maintainability in fullstack or isomorphic applications. |
| 9 | + |
| 10 | +Start provide three core environment functions: |
| 11 | + |
| 12 | +- `createIsomorphicFn`: Compose a single function that adapts to both client and server environments. |
| 13 | +- `serverOnly`: Ensures a function can only run on the server. |
| 14 | +- `clientOnly`: Ensures a function can only run on the client. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## Isomorphic Functions |
| 19 | + |
| 20 | +Use `createIsomorphicFn()` to define functions that behave differently depending on whether they are called on the client or the server. This is useful for safely sharing logic across environments while delegating environment-specific behavior to appropriate handlers. |
| 21 | + |
| 22 | +> [!WARNING] |
| 23 | +> Unimplemented function results in a no-op function. |
| 24 | +
|
| 25 | +### Complete Implementation |
| 26 | + |
| 27 | +```tsx |
| 28 | +const getEnv = createIsomorphicFn() |
| 29 | + .server(() => 'server') |
| 30 | + .client(() => 'client') |
| 31 | + |
| 32 | +const env = getEnv() |
| 33 | +// ℹ️ On the **server**, it returns `'server'`. |
| 34 | +// ℹ️ On the **client**, it returns `'client'`. |
| 35 | +``` |
| 36 | + |
| 37 | +### Partial Implementation (Server) |
| 38 | + |
| 39 | +Here is an example of `createIsomorphicFn()` with only server implementation: |
| 40 | + |
| 41 | +```tsx |
| 42 | +const serverImplementationOnly = createIsomorphicFn().server(() => 'server') |
| 43 | + |
| 44 | +const server = serverImplementationOnly() |
| 45 | +// ℹ️ On the **server**, it returns `'server'`. |
| 46 | +// ℹ️ On the **client**, it is no-op (returns `undefined`) |
| 47 | +``` |
| 48 | + |
| 49 | +### Partial Implementation (Client) |
| 50 | + |
| 51 | +Here is an example of `createIsomorphicFn()` with only client implementation: |
| 52 | + |
| 53 | +```tsx |
| 54 | +const clientImplementationOnly = createIsomorphicFn().client(() => 'client') |
| 55 | + |
| 56 | +const client = clientImplementationOnly() |
| 57 | +// ℹ️ On the **server**, it is no-op (returns `undefined`) |
| 58 | +// ℹ️ On the **client**, it returns `'client'`. |
| 59 | +``` |
| 60 | + |
| 61 | +### No Implementation |
| 62 | + |
| 63 | +Here is an example of `createIsomorphicFn()` without any environment specific implementation: |
| 64 | + |
| 65 | +```tsx |
| 66 | +const noImplementation = createIsomorphicFn() |
| 67 | + |
| 68 | +const noop = noImplementation() |
| 69 | +// ℹ️ On both **client** and **server**, it is no-op (returns `undefined`) |
| 70 | +``` |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## `env`Only Functions |
| 75 | + |
| 76 | +The `serverOnly` and `clientOnly` helpers enforce strict environment-bound execution. They ensure the decorated function is only callable in the correct runtime context. If misused, they throw descriptive runtime errors to prevent unintentional logic execution. |
| 77 | + |
| 78 | +### `serverOnly` |
| 79 | + |
| 80 | +```tsx |
| 81 | +const foo = serverOnly(() => 'bar') |
| 82 | + |
| 83 | +foo() // ✅ On server: returns "bar" |
| 84 | +// ❌ On client: throws "serverOnly() functions can only be called on the server!" |
| 85 | +``` |
| 86 | + |
| 87 | +### `clientOnly` |
| 88 | + |
| 89 | +```tsx |
| 90 | +const foo = clientOnly(() => 'bar') |
| 91 | + |
| 92 | +foo() // ✅ On client: returns "bar" |
| 93 | +// ❌ On server: throws "clientOnly() functions can only be called on the client!" |
| 94 | +``` |
| 95 | + |
| 96 | +> [!NOTE] |
| 97 | +> These functions are useful for API access, filesystem reads, using browser APIs, or other operations that are invalid or insecure outside their intended environment. |
| 98 | +
|
| 99 | +## Tree Shaking |
| 100 | + |
| 101 | +Environment functions are tree-shaken based on the environment for each bundle produced. |
| 102 | + |
| 103 | +On the server, functions created using `createIsomorphicFn()` are tree-shaken. So, all code used inside `.client()` are not included in server bundle, and vice-versa. |
| 104 | + |
| 105 | +On the server, implementation of `clientOnly` functions are replaced with a function that throws an `Error`. The reverse is true for `serverOnly` functions on the client. |
0 commit comments