@tanstack/router-core 1.168.9 → 1.168.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/hash-scroll.cjs +1 -1
- package/dist/cjs/hash-scroll.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/load-matches.cjs +6 -6
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/router.cjs +57 -58
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -1
- package/dist/cjs/scroll-restoration.cjs +1 -1
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.cjs +2 -2
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.cjs +41 -32
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.d.cts +12 -4
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.d.cts +2 -2
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -1
- package/dist/cjs/ssr/serializer/transformer.cjs +16 -14
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.d.cts +24 -23
- package/dist/cjs/ssr/ssr-client.cjs +9 -9
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +31 -9
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +3 -2
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +4 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/stores.cjs +57 -57
- package/dist/cjs/stores.cjs.map +1 -1
- package/dist/cjs/stores.d.cts +16 -16
- package/dist/esm/hash-scroll.js +1 -1
- package/dist/esm/hash-scroll.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/load-matches.js +6 -6
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/router.d.ts +3 -1
- package/dist/esm/router.js +57 -58
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +1 -1
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +2 -2
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/serializer/RawStream.d.ts +12 -4
- package/dist/esm/ssr/serializer/RawStream.js +41 -32
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.d.ts +2 -2
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.d.ts +24 -23
- package/dist/esm/ssr/serializer/transformer.js +16 -14
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/ssr-client.js +9 -9
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +3 -2
- package/dist/esm/ssr/ssr-server.js +31 -9
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +4 -1
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/stores.d.ts +16 -16
- package/dist/esm/stores.js +58 -58
- package/dist/esm/stores.js.map +1 -1
- package/package.json +3 -3
- package/src/hash-scroll.ts +1 -1
- package/src/index.ts +1 -1
- package/src/load-matches.ts +8 -11
- package/src/router.ts +74 -85
- package/src/scroll-restoration.ts +1 -1
- package/src/ssr/createRequestHandler.ts +4 -5
- package/src/ssr/serializer/RawStream.ts +65 -56
- package/src/ssr/serializer/ShallowErrorPlugin.ts +2 -2
- package/src/ssr/serializer/seroval-plugins.ts +2 -1
- package/src/ssr/serializer/transformer.ts +71 -76
- package/src/ssr/ssr-client.ts +8 -12
- package/src/ssr/ssr-server.ts +39 -7
- package/src/ssr/transformStreamWithRouter.ts +3 -0
- package/src/stores.ts +86 -86
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ReadableStreamPlugin } from 'seroval-plugins/web'
|
|
2
2
|
import { ShallowErrorPlugin } from './ShallowErrorPlugin'
|
|
3
3
|
import { RawStreamSSRPlugin } from './RawStream'
|
|
4
|
+
import type { RawStream } from './RawStream'
|
|
4
5
|
import type { Plugin } from 'seroval'
|
|
5
6
|
|
|
6
7
|
export const defaultSerovalPlugins = [
|
|
7
8
|
ShallowErrorPlugin as Plugin<Error, any>,
|
|
8
9
|
// RawStreamSSRPlugin must come before ReadableStreamPlugin to match first
|
|
9
|
-
RawStreamSSRPlugin,
|
|
10
|
+
RawStreamSSRPlugin as Plugin<RawStream, any>,
|
|
10
11
|
// ReadableStreamNode is not exported by seroval
|
|
11
12
|
ReadableStreamPlugin as Plugin<ReadableStream, any>,
|
|
12
13
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPlugin } from 'seroval'
|
|
2
2
|
import { GLOBAL_TSR } from '../constants'
|
|
3
|
-
import type { Plugin, SerovalNode } from 'seroval'
|
|
3
|
+
import type { Plugin, PluginInfo, SerovalNode } from 'seroval'
|
|
4
4
|
import type {
|
|
5
5
|
RegisteredConfigType,
|
|
6
6
|
RegisteredSsr,
|
|
@@ -14,6 +14,7 @@ declare const TSR_SERIALIZABLE: unique symbol
|
|
|
14
14
|
export type TSR_SERIALIZABLE = typeof TSR_SERIALIZABLE
|
|
15
15
|
|
|
16
16
|
export type TsrSerializable = { [TSR_SERIALIZABLE]: true }
|
|
17
|
+
|
|
17
18
|
export interface DefaultSerializable {
|
|
18
19
|
number: number
|
|
19
20
|
string: string
|
|
@@ -25,6 +26,7 @@ export interface DefaultSerializable {
|
|
|
25
26
|
Uint8Array: Uint8Array
|
|
26
27
|
RawStream: RawStream
|
|
27
28
|
TsrSerializable: TsrSerializable
|
|
29
|
+
void: void
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export interface SerializableExtensions extends DefaultSerializable {}
|
|
@@ -72,13 +74,14 @@ export interface CreateSerializationAdapterOptions<
|
|
|
72
74
|
fromSerializable: (value: TOutput) => TInput
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
export type ValidateSerializable<T, TSerializable> =
|
|
76
|
-
T
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
export type ValidateSerializable<T, TSerializable> = T extends TSerializable
|
|
78
|
+
? T
|
|
79
|
+
: T extends (...args: Array<any>) => any
|
|
80
|
+
? SerializationError<'Function may not be serializable'>
|
|
81
|
+
: T extends RegisteredReadableStream
|
|
82
|
+
? SerializationError<'JSX is not be serializable'>
|
|
83
|
+
: T extends ReadonlyArray<any>
|
|
84
|
+
? ValidateSerializableArray<T, TSerializable>
|
|
82
85
|
: T extends Promise<any>
|
|
83
86
|
? ValidateSerializablePromise<T, TSerializable>
|
|
84
87
|
: T extends ReadableStream<any>
|
|
@@ -89,9 +92,9 @@ export type ValidateSerializable<T, TSerializable> =
|
|
|
89
92
|
? ValidateSerializableMap<T, TSerializable>
|
|
90
93
|
: T extends AsyncGenerator<any, any>
|
|
91
94
|
? ValidateSerializableAsyncGenerator<T, TSerializable>
|
|
92
|
-
:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
: T extends object
|
|
96
|
+
? ValidateSerializableMapped<T, TSerializable>
|
|
97
|
+
: SerializationError<'Type may not be serializable'>
|
|
95
98
|
|
|
96
99
|
export type ValidateSerializableAsyncGenerator<T, TSerializable> =
|
|
97
100
|
T extends AsyncGenerator<infer T, infer TReturn, infer TNext>
|
|
@@ -125,16 +128,26 @@ export type ValidateSerializableMap<T, TSerializable> =
|
|
|
125
128
|
>
|
|
126
129
|
: never
|
|
127
130
|
|
|
128
|
-
export type
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
export type ValidateSerializableArray<T, TSerializable> = T extends readonly [
|
|
132
|
+
any,
|
|
133
|
+
...Array<any>,
|
|
134
|
+
]
|
|
135
|
+
? ValidateSerializableMapped<T, TSerializable>
|
|
136
|
+
: T extends Array<infer U>
|
|
137
|
+
? Array<ValidateSerializable<U, TSerializable>>
|
|
138
|
+
: T extends ReadonlyArray<infer U>
|
|
139
|
+
? ReadonlyArray<ValidateSerializable<U, TSerializable>>
|
|
140
|
+
: never
|
|
132
141
|
|
|
133
|
-
export
|
|
134
|
-
|
|
142
|
+
export type ValidateSerializableMapped<T, TSerializable> = {
|
|
143
|
+
[K in keyof T]: ValidateSerializable<T[K], TSerializable>
|
|
135
144
|
}
|
|
136
145
|
|
|
137
|
-
|
|
146
|
+
const SERIALIZATION_ERROR = Symbol.for('TSR_SERIALIZATION_ERROR')
|
|
147
|
+
|
|
148
|
+
export interface SerializationError<in out TMessage extends string> {
|
|
149
|
+
[SERIALIZATION_ERROR]: TMessage
|
|
150
|
+
}
|
|
138
151
|
|
|
139
152
|
export interface SerializationAdapter<
|
|
140
153
|
TInput,
|
|
@@ -161,27 +174,34 @@ export interface SerializationAdapterTypes<
|
|
|
161
174
|
|
|
162
175
|
export type AnySerializationAdapter = SerializationAdapter<any, any, any>
|
|
163
176
|
|
|
177
|
+
export interface AdapterNode extends PluginInfo {
|
|
178
|
+
v: SerovalNode
|
|
179
|
+
}
|
|
180
|
+
|
|
164
181
|
/** Create a Seroval plugin for server-side serialization only. */
|
|
182
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
165
183
|
export function makeSsrSerovalPlugin(
|
|
166
184
|
serializationAdapter: AnySerializationAdapter,
|
|
167
185
|
options: { didRun: boolean },
|
|
168
|
-
): Plugin<any,
|
|
169
|
-
return createPlugin<any,
|
|
186
|
+
): Plugin<any, AdapterNode> {
|
|
187
|
+
return /* @__PURE__ */ createPlugin<any, AdapterNode>({
|
|
170
188
|
tag: '$TSR/t/' + serializationAdapter.key,
|
|
171
189
|
test: serializationAdapter.test,
|
|
172
190
|
parse: {
|
|
173
|
-
stream(value, ctx) {
|
|
174
|
-
return
|
|
191
|
+
stream(value, ctx, _data) {
|
|
192
|
+
return {
|
|
193
|
+
v: ctx.parse(serializationAdapter.toSerializable(value)),
|
|
194
|
+
}
|
|
175
195
|
},
|
|
176
196
|
},
|
|
177
|
-
serialize(node, ctx) {
|
|
197
|
+
serialize(node, ctx, _data) {
|
|
178
198
|
options.didRun = true
|
|
179
199
|
return (
|
|
180
200
|
GLOBAL_TSR +
|
|
181
201
|
'.t.get("' +
|
|
182
202
|
serializationAdapter.key +
|
|
183
203
|
'")(' +
|
|
184
|
-
ctx.serialize(node) +
|
|
204
|
+
ctx.serialize(node.v) +
|
|
185
205
|
')'
|
|
186
206
|
)
|
|
187
207
|
},
|
|
@@ -191,27 +211,34 @@ export function makeSsrSerovalPlugin(
|
|
|
191
211
|
}
|
|
192
212
|
|
|
193
213
|
/** Create a Seroval plugin for client/server symmetric (de)serialization. */
|
|
214
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
194
215
|
export function makeSerovalPlugin(
|
|
195
216
|
serializationAdapter: AnySerializationAdapter,
|
|
196
|
-
): Plugin<any,
|
|
197
|
-
return createPlugin<any,
|
|
217
|
+
): Plugin<any, AdapterNode> {
|
|
218
|
+
return /* @__PURE__ */ createPlugin<any, AdapterNode>({
|
|
198
219
|
tag: '$TSR/t/' + serializationAdapter.key,
|
|
199
220
|
test: serializationAdapter.test,
|
|
200
221
|
parse: {
|
|
201
|
-
sync(value, ctx) {
|
|
202
|
-
return
|
|
222
|
+
sync(value, ctx, _data) {
|
|
223
|
+
return {
|
|
224
|
+
v: ctx.parse(serializationAdapter.toSerializable(value)),
|
|
225
|
+
}
|
|
203
226
|
},
|
|
204
|
-
async async(value, ctx) {
|
|
205
|
-
return
|
|
227
|
+
async async(value, ctx, _data) {
|
|
228
|
+
return {
|
|
229
|
+
v: await ctx.parse(serializationAdapter.toSerializable(value)),
|
|
230
|
+
}
|
|
206
231
|
},
|
|
207
|
-
stream(value, ctx) {
|
|
208
|
-
return
|
|
232
|
+
stream(value, ctx, _data) {
|
|
233
|
+
return {
|
|
234
|
+
v: ctx.parse(serializationAdapter.toSerializable(value)),
|
|
235
|
+
}
|
|
209
236
|
},
|
|
210
237
|
},
|
|
211
238
|
// we don't generate JS code outside of SSR (for now)
|
|
212
239
|
serialize: undefined as never,
|
|
213
|
-
deserialize(node, ctx) {
|
|
214
|
-
return serializationAdapter.fromSerializable(ctx.deserialize(node))
|
|
240
|
+
deserialize(node, ctx, _data) {
|
|
241
|
+
return serializationAdapter.fromSerializable(ctx.deserialize(node.v))
|
|
215
242
|
},
|
|
216
243
|
})
|
|
217
244
|
}
|
|
@@ -234,20 +261,6 @@ export type RegisteredSerializationAdapters<TRegister> = RegisteredConfigType<
|
|
|
234
261
|
'serializationAdapters'
|
|
235
262
|
>
|
|
236
263
|
|
|
237
|
-
export type ValidateSerializableInputResult<TRegister, T> =
|
|
238
|
-
ValidateSerializableResult<T, RegisteredSerializableInput<TRegister>>
|
|
239
|
-
|
|
240
|
-
export type ValidateSerializableResult<T, TSerializable> =
|
|
241
|
-
T extends ReadonlyArray<unknown>
|
|
242
|
-
? ResolveArrayShape<T, TSerializable, 'result'>
|
|
243
|
-
: T extends TSerializable
|
|
244
|
-
? T
|
|
245
|
-
: unknown extends SerializerExtensions['ReadableStream']
|
|
246
|
-
? { [K in keyof T]: ValidateSerializableResult<T[K], TSerializable> }
|
|
247
|
-
: T extends SerializerExtensions['ReadableStream']
|
|
248
|
-
? ReadableStream
|
|
249
|
-
: { [K in keyof T]: ValidateSerializableResult<T[K], TSerializable> }
|
|
250
|
-
|
|
251
264
|
export type RegisteredSSROption<TRegister> =
|
|
252
265
|
unknown extends RegisteredConfigType<TRegister, 'defaultSsr'>
|
|
253
266
|
? SSROption
|
|
@@ -282,31 +295,13 @@ export type ValidateSerializableLifecycleResultSSR<
|
|
|
282
295
|
? any
|
|
283
296
|
: ValidateSerializableInput<TRegister, LooseReturnType<TFn>>
|
|
284
297
|
|
|
285
|
-
type
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
type ResolveTupleShape<
|
|
296
|
-
T extends ReadonlyArray<unknown>,
|
|
297
|
-
TSerializable,
|
|
298
|
-
TMode extends 'input' | 'result',
|
|
299
|
-
> = T extends readonly [infer THead, ...infer TTail]
|
|
300
|
-
? readonly [
|
|
301
|
-
ArrayModeResult<TMode, THead, TSerializable>,
|
|
302
|
-
...ResolveTupleShape<Readonly<TTail>, TSerializable, TMode>,
|
|
303
|
-
]
|
|
304
|
-
: T
|
|
305
|
-
|
|
306
|
-
type ArrayModeResult<
|
|
307
|
-
TMode extends 'input' | 'result',
|
|
308
|
-
TValue,
|
|
309
|
-
TSerializable,
|
|
310
|
-
> = TMode extends 'input'
|
|
311
|
-
? ValidateSerializable<TValue, TSerializable>
|
|
312
|
-
: ValidateSerializableResult<TValue, TSerializable>
|
|
298
|
+
export type RegisteredReadableStream =
|
|
299
|
+
unknown extends SerializerExtensions['ReadableStream']
|
|
300
|
+
? never
|
|
301
|
+
: SerializerExtensions['ReadableStream']
|
|
302
|
+
|
|
303
|
+
export interface DefaultSerializerExtensions {
|
|
304
|
+
ReadableStream: unknown
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export interface SerializerExtensions extends DefaultSerializerExtensions {}
|
package/src/ssr/ssr-client.ts
CHANGED
|
@@ -95,7 +95,7 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// Hydrate the router state
|
|
98
|
-
const matches = router.matchRoutes(router.stores.location.
|
|
98
|
+
const matches = router.matchRoutes(router.stores.location.get())
|
|
99
99
|
|
|
100
100
|
// kick off loading the route chunks
|
|
101
101
|
const routeChunkPromise = Promise.all(
|
|
@@ -162,7 +162,7 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
162
162
|
}
|
|
163
163
|
})
|
|
164
164
|
|
|
165
|
-
router.stores.
|
|
165
|
+
router.stores.setMatches(matches)
|
|
166
166
|
|
|
167
167
|
// Allow the user to handle custom hydration data
|
|
168
168
|
await router.options.hydrate?.(dehydratedData)
|
|
@@ -170,8 +170,8 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
170
170
|
// now that all necessary data is hydrated:
|
|
171
171
|
// 1) fully reconstruct the route context
|
|
172
172
|
// 2) execute `head()` and `scripts()` for each match
|
|
173
|
-
const activeMatches = router.stores.
|
|
174
|
-
const location = router.stores.location.
|
|
173
|
+
const activeMatches = router.stores.matches.get()
|
|
174
|
+
const location = router.stores.location.get()
|
|
175
175
|
await Promise.all(
|
|
176
176
|
activeMatches.map(async (match) => {
|
|
177
177
|
try {
|
|
@@ -258,7 +258,7 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
258
258
|
// (e.g. preloads, invalidations) don't mistakenly detect a href change
|
|
259
259
|
// (resolvedLocation defaults to undefined and router.load() is skipped
|
|
260
260
|
// in the normal SSR hydration path).
|
|
261
|
-
router.stores.resolvedLocation.
|
|
261
|
+
router.stores.resolvedLocation.set(router.stores.location.get())
|
|
262
262
|
return routeChunkPromise
|
|
263
263
|
}
|
|
264
264
|
|
|
@@ -292,13 +292,9 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
292
292
|
// ensure router is not in status 'pending' anymore
|
|
293
293
|
// this usually happens in Transitioner but if loading synchronously resolves,
|
|
294
294
|
// Transitioner won't be rendered while loading so it cannot track the change from loading:true to loading:false
|
|
295
|
-
if (router.stores.status.
|
|
296
|
-
router.
|
|
297
|
-
|
|
298
|
-
router.stores.resolvedLocation.setState(
|
|
299
|
-
() => router.stores.location.state,
|
|
300
|
-
)
|
|
301
|
-
})
|
|
295
|
+
if (router.stores.status.get() === 'pending') {
|
|
296
|
+
router.stores.status.set('idle')
|
|
297
|
+
router.stores.resolvedLocation.set(router.stores.location.get())
|
|
302
298
|
}
|
|
303
299
|
// hide the pending component once the load is finished
|
|
304
300
|
router.updateMatch(match.id, (prev) => ({
|
package/src/ssr/ssr-server.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'
|
|
|
2
2
|
import { invariant } from '../invariant'
|
|
3
3
|
import { decodePath } from '../utils'
|
|
4
4
|
import { createLRUCache } from '../lru-cache'
|
|
5
|
+
import { rootRouteId } from '../root'
|
|
5
6
|
import minifiedTsrBootStrapScript from './tsrScript?script-string'
|
|
6
7
|
import { GLOBAL_TSR, TSR_SCRIPT_BARRIER_ID } from './constants'
|
|
7
8
|
import { dehydrateSsrMatchId } from './ssr-match-id'
|
|
@@ -171,12 +172,31 @@ function getManifestCache(manifest: Manifest): ManifestLRU {
|
|
|
171
172
|
export function attachRouterServerSsrUtils({
|
|
172
173
|
router,
|
|
173
174
|
manifest,
|
|
175
|
+
getRequestAssets,
|
|
174
176
|
}: {
|
|
175
177
|
router: AnyRouter
|
|
176
178
|
manifest: Manifest | undefined
|
|
179
|
+
getRequestAssets?: () => Array<RouterManagedTag> | undefined
|
|
177
180
|
}) {
|
|
178
181
|
router.ssr = {
|
|
179
|
-
manifest
|
|
182
|
+
get manifest() {
|
|
183
|
+
const requestAssets = getRequestAssets?.()
|
|
184
|
+
if (!requestAssets?.length) return manifest
|
|
185
|
+
// Merge request-scoped assets into root route without mutating cached manifest
|
|
186
|
+
return {
|
|
187
|
+
...manifest,
|
|
188
|
+
routes: {
|
|
189
|
+
...manifest?.routes,
|
|
190
|
+
[rootRouteId]: {
|
|
191
|
+
...manifest?.routes?.[rootRouteId],
|
|
192
|
+
assets: [
|
|
193
|
+
...requestAssets,
|
|
194
|
+
...(manifest?.routes?.[rootRouteId]?.assets ?? []),
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
},
|
|
180
200
|
}
|
|
181
201
|
let _dehydrated = false
|
|
182
202
|
let _serializationFinished = false
|
|
@@ -200,7 +220,7 @@ export function attachRouterServerSsrUtils({
|
|
|
200
220
|
const html = `<script${router.options.ssr?.nonce ? ` nonce='${router.options.ssr.nonce}'` : ''}>${script}</script>`
|
|
201
221
|
router.serverSsr!.injectHtml(html)
|
|
202
222
|
},
|
|
203
|
-
dehydrate: async () => {
|
|
223
|
+
dehydrate: async (opts?: { requestAssets?: Array<RouterManagedTag> }) => {
|
|
204
224
|
if (_dehydrated) {
|
|
205
225
|
if (process.env.NODE_ENV !== 'production') {
|
|
206
226
|
throw new Error('Invariant failed: router is already dehydrated!')
|
|
@@ -208,7 +228,7 @@ export function attachRouterServerSsrUtils({
|
|
|
208
228
|
|
|
209
229
|
invariant()
|
|
210
230
|
}
|
|
211
|
-
let matchesToDehydrate = router.stores.
|
|
231
|
+
let matchesToDehydrate = router.stores.matches.get()
|
|
212
232
|
if (router.isShell()) {
|
|
213
233
|
// In SPA mode we only want to dehydrate the root match
|
|
214
234
|
matchesToDehydrate = matchesToDehydrate.slice(0, 1)
|
|
@@ -257,6 +277,15 @@ export function attachRouterServerSsrUtils({
|
|
|
257
277
|
manifestToDehydrate = {
|
|
258
278
|
routes: filteredRoutes,
|
|
259
279
|
}
|
|
280
|
+
|
|
281
|
+
// Merge request-scoped assets into root route (without mutating cached manifest)
|
|
282
|
+
if (opts?.requestAssets?.length) {
|
|
283
|
+
const existingRoot = manifestToDehydrate.routes[rootRouteId]
|
|
284
|
+
manifestToDehydrate.routes[rootRouteId] = {
|
|
285
|
+
...existingRoot,
|
|
286
|
+
assets: [...opts.requestAssets, ...(existingRoot?.assets ?? [])],
|
|
287
|
+
}
|
|
288
|
+
}
|
|
260
289
|
}
|
|
261
290
|
const dehydratedRouter: DehydratedRouter = {
|
|
262
291
|
manifest: manifestToDehydrate,
|
|
@@ -305,6 +334,13 @@ export function attachRouterServerSsrUtils({
|
|
|
305
334
|
}
|
|
306
335
|
scriptBuffer.enqueue(serialized)
|
|
307
336
|
},
|
|
337
|
+
onError: (err: unknown) => {
|
|
338
|
+
console.error('Serialization error:', err)
|
|
339
|
+
if (err && (err as any).stack) {
|
|
340
|
+
console.error((err as any).stack)
|
|
341
|
+
}
|
|
342
|
+
signalSerializationComplete()
|
|
343
|
+
},
|
|
308
344
|
scopeId: SCOPE_ID,
|
|
309
345
|
onDone: () => {
|
|
310
346
|
scriptBuffer.enqueue(GLOBAL_TSR + '.e()')
|
|
@@ -313,10 +349,6 @@ export function attachRouterServerSsrUtils({
|
|
|
313
349
|
scriptBuffer.flush()
|
|
314
350
|
signalSerializationComplete()
|
|
315
351
|
},
|
|
316
|
-
onError: (err) => {
|
|
317
|
-
console.error('Serialization error:', err)
|
|
318
|
-
signalSerializationComplete()
|
|
319
|
-
},
|
|
320
352
|
})
|
|
321
353
|
},
|
|
322
354
|
isDehydrated() {
|
|
@@ -366,6 +366,9 @@ export function transformStreamWithRouter(
|
|
|
366
366
|
if (isAppRendering || leftover || pendingClosingTags) {
|
|
367
367
|
appendRouterHtml(html)
|
|
368
368
|
} else {
|
|
369
|
+
// App is done rendering - flush any pending buffer first to maintain order,
|
|
370
|
+
// then write the new HTML directly
|
|
371
|
+
flushPendingRouterHtml()
|
|
369
372
|
safeEnqueue(html)
|
|
370
373
|
}
|
|
371
374
|
})
|