@@ -48,6 +48,54 @@ export function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {
4848 return dehydratedMatch
4949}
5050
51+ const INITIAL_SCRIPTS = [
52+ getCrossReferenceHeader ( SCOPE_ID ) ,
53+ minifiedTsrBootStrapScript ,
54+ ]
55+
56+ class ScriptBuffer {
57+ constructor ( private router : AnyRouter ) { }
58+ private _queue : Array < string > = [ ...INITIAL_SCRIPTS ]
59+ private _scriptBarrierLifted = false
60+
61+ enqueue ( script : string ) {
62+ if ( this . _scriptBarrierLifted && this . _queue . length === 0 ) {
63+ queueMicrotask ( ( ) => {
64+ this . injectBufferedScripts ( )
65+ } )
66+ }
67+ this . _queue . push ( script )
68+ }
69+
70+ liftBarrier ( ) {
71+ if ( this . _scriptBarrierLifted ) return
72+ this . _scriptBarrierLifted = true
73+ if ( this . _queue . length > 0 ) {
74+ queueMicrotask ( ( ) => {
75+ this . injectBufferedScripts ( )
76+ } )
77+ }
78+ }
79+
80+ takeAll ( ) {
81+ const bufferedScripts = this . _queue
82+ this . _queue = [ ]
83+ if ( bufferedScripts . length === 0 ) {
84+ return undefined
85+ }
86+ bufferedScripts . push ( `${ GLOBAL_TSR } .c()` )
87+ const joinedScripts = bufferedScripts . join ( ';' )
88+ return joinedScripts
89+ }
90+
91+ injectBufferedScripts ( ) {
92+ const scriptsToInject = this . takeAll ( )
93+ if ( scriptsToInject ) {
94+ this . router . serverSsr ! . injectScript ( ( ) => scriptsToInject )
95+ }
96+ }
97+ }
98+
5199export function attachRouterServerSsrUtils ( {
52100 router,
53101 manifest,
@@ -58,16 +106,9 @@ export function attachRouterServerSsrUtils({
58106 router . ssr = {
59107 manifest,
60108 }
61- let initialScriptSent = false
62- const getInitialScript = ( ) => {
63- if ( initialScriptSent ) {
64- return ''
65- }
66- initialScriptSent = true
67- return `${ getCrossReferenceHeader ( SCOPE_ID ) } ;${ minifiedTsrBootStrapScript } ;`
68- }
69109 let _dehydrated = false
70110 const listeners : Array < ( ) => void > = [ ]
111+ const scriptBuffer = new ScriptBuffer ( router )
71112
72113 router . serverSsr = {
73114 injectedHtml : [ ] ,
@@ -84,7 +125,10 @@ export function attachRouterServerSsrUtils({
84125 injectScript : ( getScript ) => {
85126 return router . serverSsr ! . injectHtml ( async ( ) => {
86127 const script = await getScript ( )
87- return `<script ${ router . options . ssr ?. nonce ? `nonce='${ router . options . ssr . nonce } '` : '' } class='$tsr'>${ getInitialScript ( ) } ${ script } ;$_TSR.c()</script>`
128+ if ( ! script ) {
129+ return ''
130+ }
131+ return `<script${ router . options . ssr ?. nonce ? `nonce='${ router . options . ssr . nonce } ' ` : '' } class='$tsr'>${ script } </script>`
88132 } )
89133 } ,
90134 dehydrate : async ( ) => {
@@ -104,7 +148,10 @@ export function attachRouterServerSsrUtils({
104148 if ( lastMatchId ) {
105149 dehydratedRouter . lastMatchId = lastMatchId
106150 }
107- dehydratedRouter . dehydratedData = await router . options . dehydrate ?.( )
151+ const dehydratedData = await router . options . dehydrate ?.( )
152+ if ( dehydratedData ) {
153+ dehydratedRouter . dehydratedData = dehydratedData
154+ }
108155 _dehydrated = true
109156
110157 const p = createControlledPromise < string > ( )
@@ -115,6 +162,7 @@ export function attachRouterServerSsrUtils({
115162 | Array < AnySerializationAdapter >
116163 | undefined
117164 ) ?. map ( ( t ) => makeSsrSerovalPlugin ( t , trackPlugins ) ) ?? [ ]
165+
118166 crossSerializeStream ( dehydratedRouter , {
119167 refs : new Map ( ) ,
120168 plugins : [ ...plugins , ...defaultSerovalPlugins ] ,
@@ -123,10 +171,13 @@ export function attachRouterServerSsrUtils({
123171 if ( trackPlugins . didRun ) {
124172 serialized = GLOBAL_TSR + '.p(()=>' + serialized + ')'
125173 }
126- router . serverSsr ! . injectScript ( ( ) => serialized )
174+ scriptBuffer . enqueue ( serialized )
127175 } ,
128176 scopeId : SCOPE_ID ,
129- onDone : ( ) => p . resolve ( '' ) ,
177+ onDone : ( ) => {
178+ scriptBuffer . enqueue ( GLOBAL_TSR + '.streamEnd=true' )
179+ p . resolve ( '' )
180+ } ,
130181 onError : ( err ) => p . reject ( err ) ,
131182 } )
132183 // make sure the stream is kept open until the promise is resolved
@@ -138,6 +189,12 @@ export function attachRouterServerSsrUtils({
138189 onRenderFinished : ( listener ) => listeners . push ( listener ) ,
139190 setRenderFinished : ( ) => {
140191 listeners . forEach ( ( l ) => l ( ) )
192+ scriptBuffer . liftBarrier ( )
193+ } ,
194+ takeBufferedScripts ( ) {
195+ const scripts = scriptBuffer . takeAll ( )
196+ scriptBuffer . liftBarrier ( )
197+ return scripts
141198 } ,
142199 }
143200}
0 commit comments