@@ -31,43 +31,63 @@ function matchRoute(matches: any[], routes: any[], matched = []): any[] | undefi
3131 }
3232}
3333
34+ /**
35+ *
36+ *@info flattens, deduplicate by item.attrs.key and returns array of unique items respecting order of initial param.
37+ */
38+ function dedupeAssets ( assets : Asset [ ] [ ] ) : Asset [ ] {
39+ return [ ...new Map ( assets . flat ( ) . map ( item => [ item . attrs . key , item ] ) ) . values ( ) ] ;
40+ }
41+
3442/**
3543 *
3644 * Read more: https://docs.solidjs.com/solid-start/reference/server/start-server
3745 */
3846export function StartServer ( props : { document : Component < DocumentComponentProps > } ) {
39- const context = getRequestEvent ( ) as PageEvent ;
40- // @ts -ignore
47+ const context = getRequestEvent ( ) as PageEvent & { nonce ?: string } ;
48+
4149 const nonce = context . nonce ;
4250
4351 let assets : Asset [ ] = [ ] ;
4452 Promise . resolve ( ) . then ( async ( ) => {
4553 let assetPromises : Promise < Asset [ ] > [ ] = [ ] ;
46- // @ts -ignore
54+ // @ts -expect-error - context.router is not typed
4755 if ( context . router && context . router . matches ) {
48- // @ts -ignore
56+ // @ts -expect-error - context.router is not typed
4957 const matches = [ ...context . router . matches ] ;
5058 while ( matches . length && ( ! matches [ 0 ] . info || ! matches [ 0 ] . info . filesystem ) ) matches . shift ( ) ;
5159 const matched = matches . length && matchRoute ( matches , context . routes ) ;
5260 if ( matched ) {
5361 const inputs = import . meta. env . MANIFEST [ import . meta. env . START_ISLANDS ? "ssr" : "client" ] !
54- . inputs
62+ . inputs ;
5563 for ( let i = 0 ; i < matched . length ; i ++ ) {
5664 const segment = matched [ i ] ;
5765 const part = inputs [ segment [ "$component" ] . src ] ! ;
5866 assetPromises . push ( part . assets ( ) as any ) ;
5967 }
6068 } else if ( import . meta. env . DEV ) console . warn ( "No route matched for preloading js assets" ) ;
6169 }
62- assets = await Promise . all ( assetPromises ) . then ( a =>
63- // dedupe assets
64- [ ...new Map ( a . flat ( ) . map ( item => [ item . attrs . key , item ] ) ) . values ( ) ] . filter ( asset =>
65- import . meta. env . START_ISLANDS
66- ? false
67- : ( asset . attrs as JSX . LinkHTMLAttributes < HTMLLinkElement > ) . rel === "modulepreload" &&
70+ assets = await Promise . all ( assetPromises ) . then ( assetList => {
71+ if ( import . meta. env . START_ISLANDS ) {
72+ return [ ] ;
73+ } else {
74+ return dedupeAssets ( assetList ) . filter ( asset => {
75+ const assetAttrs = asset . attrs as JSX . LinkHTMLAttributes < HTMLLinkElement > ;
76+
77+ /**
78+ * @info besides `modulepreload` we also want `stylesheet` to be preloaded during SSR.
79+ * this will prevent FOUC on the client for non-global CSS.
80+ */
81+ const isPreloadOrStylesheet =
82+ assetAttrs . rel === "modulepreload" || assetAttrs . rel === "stylesheet" ;
83+
84+ return (
85+ isPreloadOrStylesheet &&
6886 ! context . assets . find ( ( a : Asset ) => a . attrs . key === asset . attrs . key )
69- )
70- ) ;
87+ ) ;
88+ } ) ;
89+ }
90+ } ) ;
7191 } ) ;
7292
7393 useAssets ( ( ) => ( assets . length ? assets . map ( m => renderAsset ( m ) ) : undefined ) ) ;
0 commit comments