11import type { ActionManifest } from '../../build/webpack/plugins/flight-client-entry-plugin'
2- import type { ClientReferenceManifest } from '../../build/webpack/plugins/flight-manifest-plugin'
2+ import type {
3+ ClientReferenceManifest ,
4+ ClientReferenceManifestForRsc ,
5+ } from '../../build/webpack/plugins/flight-manifest-plugin'
36import type { DeepReadonly } from '../../shared/lib/deep-readonly'
7+ import { InvariantError } from '../../shared/lib/invariant-error'
8+ import { workAsyncStorage } from './work-async-storage.external'
49
510let __next_loaded_action_key : CryptoKey
611
@@ -64,10 +69,12 @@ const SERVER_ACTION_MANIFESTS_SINGLETON = Symbol.for(
6469)
6570
6671export function setReferenceManifestsSingleton ( {
72+ page,
6773 clientReferenceManifest,
6874 serverActionsManifest,
6975 serverModuleMap,
7076} : {
77+ page : string
7178 clientReferenceManifest : DeepReadonly < ClientReferenceManifest >
7279 serverActionsManifest : DeepReadonly < ActionManifest >
7380 serverModuleMap : {
@@ -78,9 +85,19 @@ export function setReferenceManifestsSingleton({
7885 }
7986 }
8087} ) {
81- // @ts -ignore
88+ // @ts -expect-error
89+ const clientReferenceManifestsPerPage = globalThis [
90+ SERVER_ACTION_MANIFESTS_SINGLETON
91+ ] ?. clientReferenceManifestsPerPage as
92+ | undefined
93+ | DeepReadonly < Record < string , ClientReferenceManifest > >
94+
95+ // @ts -expect-error
8296 globalThis [ SERVER_ACTION_MANIFESTS_SINGLETON ] = {
83- clientReferenceManifest,
97+ clientReferenceManifestsPerPage : {
98+ ...clientReferenceManifestsPerPage ,
99+ [ normalizePage ( page ) ] : clientReferenceManifest ,
100+ } ,
84101 serverActionsManifest,
85102 serverModuleMap,
86103 }
@@ -100,29 +117,49 @@ export function getServerModuleMap() {
100117 }
101118
102119 if ( ! serverActionsManifestSingleton ) {
103- throw new Error (
104- 'Missing manifest for Server Actions. This is a bug in Next.js'
105- )
120+ throw new InvariantError ( 'Missing manifest for Server Actions.' )
106121 }
107122
108123 return serverActionsManifestSingleton . serverModuleMap
109124}
110125
111- export function getClientReferenceManifestSingleton ( ) {
126+ export function getClientReferenceManifestForRsc ( ) : DeepReadonly < ClientReferenceManifestForRsc > {
112127 const serverActionsManifestSingleton = ( globalThis as any ) [
113128 SERVER_ACTION_MANIFESTS_SINGLETON
114129 ] as {
115- clientReferenceManifest : DeepReadonly < ClientReferenceManifest >
116- serverActionsManifest : DeepReadonly < ActionManifest >
130+ clientReferenceManifestsPerPage : DeepReadonly <
131+ Record < string , ClientReferenceManifest >
132+ >
117133 }
118134
119135 if ( ! serverActionsManifestSingleton ) {
120- throw new Error (
121- 'Missing manifest for Server Actions. This is a bug in Next.js'
122- )
136+ throw new InvariantError ( 'Missing manifest for Server Actions.' )
137+ }
138+
139+ const { clientReferenceManifestsPerPage } = serverActionsManifestSingleton
140+ const workStore = workAsyncStorage . getStore ( )
141+
142+ if ( ! workStore ) {
143+ // If there's no work store defined, we can assume that a client reference
144+ // manifest is needed during module evaluation, e.g. to create a server
145+ // action using a higher-order function. This might also use client
146+ // components which need to be serialized by Flight, and therefore client
147+ // references need to be resolvable. To make this work, we're returning a
148+ // merged manifest across all pages. This is fine as long as the module IDs
149+ // are not page specific, which they are not for Webpack. TODO: Fix this in
150+ // Turbopack.
151+ return mergeClientReferenceManifests ( clientReferenceManifestsPerPage )
123152 }
124153
125- return serverActionsManifestSingleton . clientReferenceManifest
154+ const page = normalizePage ( workStore . page )
155+
156+ const clientReferenceManifest = clientReferenceManifestsPerPage [ page ]
157+
158+ if ( ! clientReferenceManifest ) {
159+ throw new InvariantError ( `Missing Client Reference Manifest for ${ page } .` )
160+ }
161+
162+ return clientReferenceManifest
126163}
127164
128165export async function getActionEncryptionKey ( ) {
@@ -133,22 +170,19 @@ export async function getActionEncryptionKey() {
133170 const serverActionsManifestSingleton = ( globalThis as any ) [
134171 SERVER_ACTION_MANIFESTS_SINGLETON
135172 ] as {
136- clientReferenceManifest : DeepReadonly < ClientReferenceManifest >
137173 serverActionsManifest : DeepReadonly < ActionManifest >
138174 }
139175
140176 if ( ! serverActionsManifestSingleton ) {
141- throw new Error (
142- 'Missing manifest for Server Actions. This is a bug in Next.js'
143- )
177+ throw new InvariantError ( 'Missing manifest for Server Actions.' )
144178 }
145179
146180 const rawKey =
147181 process . env . NEXT_SERVER_ACTIONS_ENCRYPTION_KEY ||
148182 serverActionsManifestSingleton . serverActionsManifest . encryptionKey
149183
150184 if ( rawKey === undefined ) {
151- throw new Error ( 'Missing encryption key for Server Actions' )
185+ throw new InvariantError ( 'Missing encryption key for Server Actions' )
152186 }
153187
154188 __next_loaded_action_key = await crypto . subtle . importKey (
@@ -161,3 +195,40 @@ export async function getActionEncryptionKey() {
161195
162196 return __next_loaded_action_key
163197}
198+
199+ function normalizePage ( page : string ) : string {
200+ return page . replace ( / \/ ( p a g e | r o u t e ) $ / , '' )
201+ }
202+
203+ function mergeClientReferenceManifests (
204+ clientReferenceManifestsPerPage : DeepReadonly <
205+ Record < string , ClientReferenceManifest >
206+ >
207+ ) : ClientReferenceManifestForRsc {
208+ const clientReferenceManifests = Object . values (
209+ clientReferenceManifestsPerPage as Record < string , ClientReferenceManifest >
210+ )
211+
212+ const mergedClientReferenceManifest : ClientReferenceManifestForRsc = {
213+ clientModules : { } ,
214+ edgeRscModuleMapping : { } ,
215+ rscModuleMapping : { } ,
216+ }
217+
218+ for ( const clientReferenceManifest of clientReferenceManifests ) {
219+ mergedClientReferenceManifest . clientModules = {
220+ ...mergedClientReferenceManifest . clientModules ,
221+ ...clientReferenceManifest . clientModules ,
222+ }
223+ mergedClientReferenceManifest . edgeRscModuleMapping = {
224+ ...mergedClientReferenceManifest . edgeRscModuleMapping ,
225+ ...clientReferenceManifest . edgeRscModuleMapping ,
226+ }
227+ mergedClientReferenceManifest . rscModuleMapping = {
228+ ...mergedClientReferenceManifest . rscModuleMapping ,
229+ ...clientReferenceManifest . rscModuleMapping ,
230+ }
231+ }
232+
233+ return mergedClientReferenceManifest
234+ }
0 commit comments