Skip to content

Commit 02276b1

Browse files
refactor: start compiler (#5014)
1 parent dd2d3ca commit 02276b1

File tree

29 files changed

+635
-564
lines changed

29 files changed

+635
-564
lines changed

docs/start/framework/react/how-to/write-isomorphic-client-server-code.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ export const Route = createFileRoute('/products')({
3535

3636
### Server-Only APIs
3737

38-
| API | Use Case | Client Behavior |
39-
| ------------------ | ------------------------- | ------------------------- |
40-
| `createServerFn()` | RPC calls, data mutations | Network request to server |
41-
| `serverOnly(fn)` | Utility functions | Throws error |
38+
| API | Use Case | Client Behavior |
39+
| ------------------------ | ------------------------- | ------------------------- |
40+
| `createServerFn()` | RPC calls, data mutations | Network request to server |
41+
| `createServerOnlyFn(fn)` | Utility functions | Throws error |
4242

4343
```tsx
44-
import { createServerFn, serverOnly } from '@tanstack/react-start'
44+
import { createServerFn, createServerOnlyFn } from '@tanstack/react-start'
4545

4646
// RPC: Server execution, callable from client
4747
const updateUser = createServerFn({ method: 'POST' })
@@ -52,22 +52,22 @@ const updateUser = createServerFn({ method: 'POST' })
5252
})
5353

5454
// Utility: Server-only, client crashes if called
55-
const getEnvVar = serverOnly(() => process.env.DATABASE_URL)
55+
const getEnvVar = createServerOnlyFn(() => process.env.DATABASE_URL)
5656
```
5757

5858
### Client-Only APIs
5959

60-
| API | Use Case | Server Behavior |
61-
| ---------------- | ------------------------------- | ---------------- |
62-
| `clientOnly(fn)` | Browser utilities | Throws error |
63-
| `<ClientOnly>` | Components needing browser APIs | Renders fallback |
60+
| API | Use Case | Server Behavior |
61+
| ------------------------ | ------------------------------- | ---------------- |
62+
| `createClientOnlyFn(fn)` | Browser utilities | Throws error |
63+
| `<ClientOnly>` | Components needing browser APIs | Renders fallback |
6464

6565
```tsx
66-
import { clientOnly } from '@tanstack/react-start'
66+
import { createClientOnlyFn } from '@tanstack/react-start'
6767
import { ClientOnly } from '@tanstack/react-router'
6868

6969
// Utility: Client-only, server crashes if called
70-
const saveToStorage = clientOnly((key: string, value: any) => {
70+
const saveToStorage = createClientOnlyFn((key: string, value: any) => {
7171
localStorage.setItem(key, JSON.stringify(value))
7272
})
7373

@@ -96,7 +96,7 @@ const getDeviceInfo = createIsomorphicFn()
9696

9797
## Key Distinctions
9898

99-
### `createServerFn()` vs `serverOnly()`
99+
### `createServerFn()` vs `createServerOnlyFn()`
100100

101101
```tsx
102102
// createServerFn: RPC pattern - server execution, client callable
@@ -105,8 +105,8 @@ const fetchUser = createServerFn().handler(async () => await db.users.find())
105105
// Usage from client component:
106106
const user = await fetchUser() // ✅ Network request
107107

108-
// serverOnly: Crashes if called from client
109-
const getSecret = serverOnly(() => process.env.SECRET)
108+
// createServerOnlyFn: Crashes if called from client
109+
const getSecret = createServerOnlyFn(() => process.env.SECRET)
110110

111111
// Usage from client:
112112
const secret = getSecret() // ❌ Throws error
@@ -182,7 +182,7 @@ const storage = createIsomorphicFn()
182182
const apiKey = process.env.SECRET_KEY
183183

184184
// ✅ Server-only access
185-
const apiKey = serverOnly(() => process.env.SECRET_KEY)
185+
const apiKey = createServerOnlyFn(() => process.env.SECRET_KEY)
186186
```
187187

188188
### Incorrect Loader Assumptions
@@ -233,7 +233,7 @@ function CurrentTime() {
233233
## Production Checklist
234234

235235
- [ ] **Bundle Analysis**: Verify server-only code isn't in client bundle
236-
- [ ] **Environment Variables**: Ensure secrets use `serverOnly()` or `createServerFn()`
236+
- [ ] **Environment Variables**: Ensure secrets use `createServerOnlyFn()` or `createServerFn()`
237237
- [ ] **Loader Logic**: Remember loaders are isomorphic, not server-only
238238
- [ ] **ClientOnly Fallbacks**: Provide appropriate fallbacks to prevent layout shift
239239
- [ ] **Error Boundaries**: Handle server/client execution errors gracefully

e2e/react-start/server-functions/src/routes/env-only.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { createFileRoute } from '@tanstack/react-router'
2-
import { clientOnly, createServerFn, serverOnly } from '@tanstack/react-start'
2+
import {
3+
createClientOnlyFn,
4+
createServerFn,
5+
createServerOnlyFn,
6+
} from '@tanstack/react-start'
37
import { useState } from 'react'
48

5-
const serverEcho = serverOnly((input: string) => 'server got: ' + input)
6-
const clientEcho = clientOnly((input: string) => 'client got: ' + input)
9+
const serverEcho = createServerOnlyFn((input: string) => 'server got: ' + input)
10+
const clientEcho = createClientOnlyFn((input: string) => 'client got: ' + input)
711

812
const testOnServer = createServerFn().handler(() => {
913
const serverOnServer = serverEcho('hello')

e2e/react-start/server-functions/tests/server-functions.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ test('env-only functions can only be called on the server or client respectively
119119
'server got: hello',
120120
)
121121
await expect(page.getByTestId('server-on-client')).toContainText(
122-
'serverEcho threw an error: serverOnly() functions can only be called on the server!',
122+
'serverEcho threw an error: createServerOnlyFn() functions can only be called on the server!',
123123
)
124124

125125
await expect(page.getByTestId('client-on-server')).toContainText(
126-
'clientEcho threw an error: clientOnly() functions can only be called on the client!',
126+
'clientEcho threw an error: createClientOnlyFn() functions can only be called on the client!',
127127
)
128128
await expect(page.getByTestId('client-on-client')).toContainText(
129129
'client got: hello',

e2e/solid-start/server-functions/src/routes/env-only.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { createFileRoute } from '@tanstack/solid-router'
2-
import { clientOnly, createServerFn, serverOnly } from '@tanstack/solid-start'
2+
import {
3+
createClientOnlyFn,
4+
createServerFn,
5+
createServerOnlyFn,
6+
} from '@tanstack/solid-start'
37
import { createSignal } from 'solid-js'
48

5-
const serverEcho = serverOnly((input: string) => 'server got: ' + input)
6-
const clientEcho = clientOnly((input: string) => 'client got: ' + input)
9+
const serverEcho = createServerOnlyFn((input: string) => 'server got: ' + input)
10+
const clientEcho = createClientOnlyFn((input: string) => 'client got: ' + input)
711

812
const testOnServer = createServerFn().handler(() => {
913
const serverOnServer = serverEcho('hello')

e2e/solid-start/server-functions/tests/server-functions.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ test('env-only functions can only be called on the server or client respectively
117117
'server got: hello',
118118
)
119119
await expect(page.getByTestId('server-on-client')).toContainText(
120-
'serverEcho threw an error: serverOnly() functions can only be called on the server!',
120+
'serverEcho threw an error: createServerOnlyFn() functions can only be called on the server!',
121121
)
122122

123123
await expect(page.getByTestId('client-on-server')).toContainText(
124-
'clientEcho threw an error: clientOnly() functions can only be called on the client!',
124+
'clientEcho threw an error: createClientOnlyFn() functions can only be called on the client!',
125125
)
126126
await expect(page.getByTestId('client-on-client')).toContainText(
127127
'client got: hello',

packages/react-start-client/src/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ export {
55
createMiddleware,
66
registerGlobalMiddleware,
77
globalMiddleware,
8-
serverOnly,
9-
clientOnly,
8+
createServerOnlyFn,
9+
createClientOnlyFn,
1010
json,
1111
createClientRpc,
1212
} from '@tanstack/start-client-core'

packages/solid-start-client/src/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ export {
55
createMiddleware,
66
registerGlobalMiddleware,
77
globalMiddleware,
8-
serverOnly,
9-
clientOnly,
8+
createServerOnlyFn,
9+
createClientOnlyFn,
1010
json,
1111
createClientRpc,
1212
} from '@tanstack/start-client-core'

packages/start-client-core/src/envOnly.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn
22

33
// A function that will only be available in the server build
44
// If called on the client, it will throw an error
5-
export const serverOnly: EnvOnlyFn = (fn) => fn
5+
export const createServerOnlyFn: EnvOnlyFn = (fn) => fn
66

77
// A function that will only be available in the client build
88
// If called on the server, it will throw an error
9-
export const clientOnly: EnvOnlyFn = (fn) => fn
9+
export const createClientOnlyFn: EnvOnlyFn = (fn) => fn

packages/start-client-core/src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export {
2121
type ClientOnlyFn,
2222
type IsomorphicFnBase,
2323
} from './createIsomorphicFn'
24-
export { serverOnly, clientOnly } from './envOnly'
24+
export { createServerOnlyFn, createClientOnlyFn } from './envOnly'
2525
export { createServerFn } from './createServerFn'
2626
export {
2727
createMiddleware,
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expectTypeOf, test } from 'vitest'
2-
import { clientOnly, serverOnly } from '../envOnly'
2+
import { createClientOnlyFn, createServerOnlyFn } from '../envOnly'
33

44
const inputFn = () => 'output'
55

@@ -11,24 +11,24 @@ function overloadedFn(input: any) {
1111
return input
1212
}
1313

14-
test("clientOnly returns the function it's given", () => {
15-
const outputFn = clientOnly(inputFn)
14+
test("createClientOnlyFn returns the function it's given", () => {
15+
const outputFn = createClientOnlyFn(inputFn)
1616
expectTypeOf(outputFn).toEqualTypeOf<typeof inputFn>()
1717

18-
const genericOutputFn = clientOnly(genericInputFn)
18+
const genericOutputFn = createClientOnlyFn(genericInputFn)
1919
expectTypeOf(genericOutputFn).toEqualTypeOf<typeof genericInputFn>()
2020

21-
const overloadedOutputFn = clientOnly(overloadedFn)
21+
const overloadedOutputFn = createClientOnlyFn(overloadedFn)
2222
expectTypeOf(overloadedOutputFn).toEqualTypeOf<typeof overloadedFn>()
2323
})
2424

25-
test("serverOnly returns the function it's given", () => {
26-
const outputFn = serverOnly(inputFn)
25+
test("createServerOnlyFn returns the function it's given", () => {
26+
const outputFn = createServerOnlyFn(inputFn)
2727
expectTypeOf(outputFn).toEqualTypeOf<typeof inputFn>()
2828

29-
const genericOutputFn = serverOnly(genericInputFn)
29+
const genericOutputFn = createServerOnlyFn(genericInputFn)
3030
expectTypeOf(genericOutputFn).toEqualTypeOf<typeof genericInputFn>()
3131

32-
const overloadedOutputFn = serverOnly(overloadedFn)
32+
const overloadedOutputFn = createServerOnlyFn(overloadedFn)
3333
expectTypeOf(overloadedOutputFn).toEqualTypeOf<typeof overloadedFn>()
3434
})

0 commit comments

Comments
 (0)