-
-
Notifications
You must be signed in to change notification settings - Fork 247
Expand file tree
/
Copy pathrsc.ts
More file actions
145 lines (133 loc) · 4.07 KB
/
rsc.ts
File metadata and controls
145 lines (133 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { memoize, tinyassert } from '@hiogawa/utils'
import type { BundlerConfig, ImportManifestEntry, ModuleMap } from '../types'
import {
SERVER_DECODE_CLIENT_PREFIX,
SERVER_REFERENCE_PREFIX,
createReferenceCacheTag,
removeReferenceCacheTag,
setInternalRequire,
} from './shared'
// @ts-ignore
import * as ReactServer from '@vitejs/plugin-rsc/vendor/react-server-dom/server.edge'
let init = false
let requireModule!: (id: string) => unknown
export function setRequireModule(options: {
load: (id: string) => unknown
}): void {
if (init) return
init = true
requireModule = (id) => {
return options.load(removeReferenceCacheTag(id))
}
// need memoize to return stable promise from __webpack_require__
;(globalThis as any).__vite_rsc_server_require__ = memoize(
async (id: string) => {
if (id.startsWith(SERVER_DECODE_CLIENT_PREFIX)) {
// decode client reference on the server
id = id.slice(SERVER_DECODE_CLIENT_PREFIX.length)
id = removeReferenceCacheTag(id)
// create `registerClientReference` on the fly since there's no way to
// grab the original client reference module on ther server.
// cf. https://github.com/lazarv/react-server/blob/79e7acebc6f4a8c930ad8422e2a4a9fdacfcce9b/packages/react-server/server/module-loader.mjs#L19
const target = {} as any
const getOrCreateClientReference = (name: string) => {
return (target[name] ??= ReactServer.registerClientReference(
() => {
throw new Error(
`Unexpectedly client reference export '${name}' is called on server`,
)
},
id,
name,
))
}
return new Proxy(target, {
// React 19.2.1+ uses hasOwnProperty.call() to check for exports
// https://github.com/facebook/react/pull/35277
getOwnPropertyDescriptor(_target, name) {
if (typeof name !== 'string' || name === 'then') {
return Reflect.getOwnPropertyDescriptor(target, name)
}
getOrCreateClientReference(name)
return Reflect.getOwnPropertyDescriptor(target, name)
},
})
}
return requireModule(id)
},
)
setInternalRequire()
}
export async function loadServerAction(id: string): Promise<Function> {
const [file, name] = id.split('#') as [string, string]
const mod: any = await requireModule(file)
return mod[name]
}
export function createServerManifest(): BundlerConfig {
const cacheTag = import.meta.env.DEV ? createReferenceCacheTag() : ''
return new Proxy(
{},
{
get(_target, $$id, _receiver) {
tinyassert(typeof $$id === 'string')
let [id, name] = $$id.split('#')
tinyassert(id)
tinyassert(name)
return {
id: SERVER_REFERENCE_PREFIX + id + cacheTag,
name,
chunks: [],
async: true,
} satisfies ImportManifestEntry
},
},
)
}
export function createServerDecodeClientManifest(): ModuleMap {
return new Proxy(
{},
{
get(_target, id: string) {
return new Proxy(
{},
{
get(_target, name: string) {
return {
id: SERVER_REFERENCE_PREFIX + SERVER_DECODE_CLIENT_PREFIX + id,
name,
chunks: [],
async: true,
}
},
},
)
},
},
)
}
export function createClientManifest(options?: {
/**
* @internal
*/
onClientReference?: (metadata: { id: string; name: string }) => void
}): BundlerConfig {
const cacheTag = import.meta.env.DEV ? createReferenceCacheTag() : ''
return new Proxy(
{},
{
get(_target, $$id, _receiver) {
tinyassert(typeof $$id === 'string')
let [id, name] = $$id.split('#')
tinyassert(id)
tinyassert(name)
options?.onClientReference?.({ id, name })
return {
id: id + cacheTag,
name,
chunks: [],
async: true,
} satisfies ImportManifestEntry
},
},
)
}