@@ -121,10 +121,14 @@ export class ReactRenderer implements Renderer {
121
121
122
122
/** Given a node-land module id (path), return the build time path to the virtual script to hydrate the render client side */
123
123
public buildVirtualClientEntrypointModuleID ( route : RenderableRoute ) {
124
+ const queryParams = {
125
+ layout : route . layout ,
126
+ base : route . base ,
127
+ ...( route . isImperative && { route : route . url , component : route . renderable } ) ,
128
+ }
129
+
124
130
return (
125
- path . join ( CLIENT_ENTRYPOINT_PREFIX , route . renderable , 'hydrate.jsx' ) +
126
- '?' +
127
- querystring . stringify ( { layout : route . layout , base : route . base } )
131
+ path . join ( CLIENT_ENTRYPOINT_PREFIX , route . renderable , 'hydrate.jsx' ) + '?' + querystring . stringify ( queryParams )
128
132
)
129
133
}
130
134
@@ -189,7 +193,6 @@ export class ReactRenderer implements Renderer {
189
193
// push the props for the entrypoint to use when hydrating client side
190
194
bus . push ( 'tail' , `<script type="module">window.__FSTR_PROPS=${ JSON . stringify ( render . props ) } ;</script>` )
191
195
192
- const entrypointName = this . buildVirtualClientEntrypointModuleID ( render )
193
196
// if we're in development, we just source the entrypoint directly from vite and let the browser do its thing importing all the referenced stuff
194
197
if ( this . plugin . devMode ) {
195
198
bus . push (
@@ -200,6 +203,7 @@ export class ReactRenderer implements Renderer {
200
203
) } "></script>`
201
204
)
202
205
} else {
206
+ const entrypointName = this . buildVirtualClientEntrypointModuleID ( render )
203
207
const manifestEntryName = normalizePath ( path . relative ( this . viteConfig . root , entrypointName ) )
204
208
this . plugin . pushImportTagsFromManifest ( bus , manifestEntryName )
205
209
}
@@ -309,13 +313,16 @@ export class ReactRenderer implements Renderer {
309
313
const entrypoint = id . replace ( CLIENT_ENTRYPOINT_PREFIX , '/@fs/' ) . replace ( / \/ h y d r a t e \. j s x \? .+ $ / , '' )
310
314
const layout = url . searchParams . get ( 'layout' ) !
311
315
const base = url . searchParams . get ( 'base' ) !
316
+ const route = url . searchParams . get ( 'route' ) !
317
+ const component = url . searchParams . get ( 'component' ) !
318
+ const queryParams = { base, lazy : true , ...( component && { route, component } ) }
312
319
313
320
return `
314
321
// client side hydration entrypoint for a particular route generated by fastify-renderer
315
322
import React from 'react'
316
323
import ReactDOM from 'react-dom'
317
324
import { routes } from ${ JSON . stringify (
318
- ReactRenderer . ROUTE_TABLE_ID + '?' + querystring . stringify ( { base , lazy : true } )
325
+ ReactRenderer . ROUTE_TABLE_ID + '?' + querystring . stringify ( queryParams )
319
326
) }
320
327
import { Root } from ${ JSON . stringify ( this . clientModulePath ) }
321
328
import Layout from ${ JSON . stringify ( layout ) }
@@ -411,9 +418,19 @@ export class ReactRenderer implements Renderer {
411
418
const url = new URL ( 'fstr://' + id )
412
419
const lazy = ! ! url . searchParams . get ( 'lazy' ) !
413
420
const base = url . searchParams . get ( 'base' ) !
421
+ const route = url . searchParams . get ( 'route' ) !
422
+ const component = url . searchParams . get ( 'component' ) !
414
423
// We filter out the routes the imperatively renderable routes, which don't have a url property
415
424
// There is no point in having them included in the route table
416
425
const applicableRoutes = this . routes . filter ( ( route ) => route . base == base && route . url !== undefined )
426
+ if ( route ) {
427
+ const imperativeRoute = Object . assign (
428
+ { } ,
429
+ this . routes . find ( ( route ) => ( route . renderable = component ) ) ,
430
+ { url : route }
431
+ )
432
+ applicableRoutes . push ( imperativeRoute )
433
+ }
417
434
applicableRoutes . sort ( ( a , b ) => routeSortScore ( a . url ! ) - routeSortScore ( b . url ! ) )
418
435
419
436
const pathsToModules = applicableRoutes . map ( ( route ) => [
0 commit comments