@@ -242,10 +242,8 @@ export default function vitePluginRsc(
242242 serverResourcesMetaMap = sortObject ( serverResourcesMetaMap )
243243 await builder . build ( builder . environments . client ! )
244244
245- const assetsManifestCode = `export default ${ JSON . stringify (
245+ const assetsManifestCode = `export default ${ serializeValueWithRuntime (
246246 buildAssetsManifest ,
247- null ,
248- 2 ,
249247 ) } `
250248 const manifestPath = path . join (
251249 builder . environments ! . rsc ! . config . build ! . outDir ! ,
@@ -586,7 +584,7 @@ export default function vitePluginRsc(
586584 assert ( this . environment . mode === 'dev' )
587585 const entryUrl = assetsURL ( '@id/__x00__' + VIRTUAL_ENTRIES . browser )
588586 const manifest : AssetsManifest = {
589- bootstrapScriptContent : `import(${ JSON . stringify ( entryUrl ) } )` ,
587+ bootstrapScriptContent : `import(${ serializeValueWithRuntime ( entryUrl ) } )` ,
590588 clientReferenceDeps : { } ,
591589 }
592590 return `export default ${ JSON . stringify ( manifest , null , 2 ) } `
@@ -640,8 +638,16 @@ export default function vitePluginRsc(
640638 mergeAssetDeps ( deps , entry . deps ) ,
641639 )
642640 }
641+ let bootstrapScriptContent : string | RuntimeAsset
642+ if ( typeof entryUrl === 'string' ) {
643+ bootstrapScriptContent = `import(${ JSON . stringify ( entryUrl ) } )`
644+ } else {
645+ bootstrapScriptContent = new RuntimeAsset (
646+ `"import(" + JSON.stringify(${ entryUrl . runtime } ) + ")"` ,
647+ )
648+ }
643649 buildAssetsManifest = {
644- bootstrapScriptContent : `import( ${ JSON . stringify ( entryUrl ) } )` ,
650+ bootstrapScriptContent,
645651 clientReferenceDeps,
646652 serverResources,
647653 }
@@ -671,10 +677,8 @@ export default function vitePluginRsc(
671677 if ( this . environment . name === 'ssr' ) {
672678 // output client manifest to non-client build directly.
673679 // this makes server build to be self-contained and deploy-able for cloudflare.
674- const assetsManifestCode = `export default ${ JSON . stringify (
680+ const assetsManifestCode = `export default ${ serializeValueWithRuntime (
675681 buildAssetsManifest ,
676- null ,
677- 2 ,
678682 ) } `
679683 for ( const name of [ 'ssr' , 'rsc' ] ) {
680684 const manifestPath = path . join (
@@ -1273,15 +1277,76 @@ function generateDynamicImportCode(map: Record<string, string>) {
12731277 return `export default {${ code } };\n`
12741278}
12751279
1276- // // https://github.com/vitejs/vite/blob/2a7473cfed96237711cda9f736465c84d442ddef/packages/vite/src/node/plugins/importAnalysisBuild.ts#L222-L230
1280+ class RuntimeAsset {
1281+ runtime : string
1282+ constructor ( value : string ) {
1283+ this . runtime = value
1284+ }
1285+ }
1286+
1287+ function serializeValueWithRuntime ( value : any ) {
1288+ const replacements : [ string , string ] [ ] = [ ]
1289+ let result = JSON . stringify (
1290+ value ,
1291+ ( _key , value ) => {
1292+ if ( value instanceof RuntimeAsset ) {
1293+ const placeholder = `__runtime_placeholder_${ replacements . length } __`
1294+ replacements . push ( [ placeholder , value . runtime ] )
1295+ return placeholder
1296+ }
1297+
1298+ return value
1299+ } ,
1300+ 2 ,
1301+ )
1302+
1303+ for ( const [ placeholder , runtime ] of replacements ) {
1304+ result = result . replace ( `"${ placeholder } "` , runtime )
1305+ }
1306+
1307+ return result
1308+ }
1309+
12771310function assetsURL ( url : string ) {
1311+ if (
1312+ config . command === 'build' &&
1313+ typeof config . experimental ?. renderBuiltUrl === 'function'
1314+ ) {
1315+ // https://github.com/vitejs/vite/blob/bdde0f9e5077ca1a21a04eefc30abad055047226/packages/vite/src/node/build.ts#L1369
1316+ const result = config . experimental . renderBuiltUrl ( url , {
1317+ type : 'asset' ,
1318+ hostType : 'js' ,
1319+ ssr : true ,
1320+ hostId : '' ,
1321+ } )
1322+
1323+ if ( typeof result === 'object' ) {
1324+ if ( result . runtime ) {
1325+ return new RuntimeAsset ( result . runtime )
1326+ }
1327+ assert (
1328+ ! result . relative ,
1329+ '"result.relative" not supported on renderBuiltUrl() for RSC' ,
1330+ )
1331+ } else if ( result ) {
1332+ return result satisfies string
1333+ }
1334+ }
1335+
1336+ // https://github.com/vitejs/vite/blob/2a7473cfed96237711cda9f736465c84d442ddef/packages/vite/src/node/plugins/importAnalysisBuild.ts#L222-L230
12781337 return config . base + url
12791338}
12801339
12811340function assetsURLOfDeps ( deps : AssetDeps ) {
12821341 return {
1283- js : deps . js . map ( ( href ) => assetsURL ( href ) ) ,
1284- css : deps . css . map ( ( href ) => assetsURL ( href ) ) ,
1342+ js : deps . js . map ( ( href ) => {
1343+ assert ( typeof href === 'string' )
1344+ return assetsURL ( href )
1345+ } ) ,
1346+ css : deps . css . map ( ( href ) => {
1347+ assert ( typeof href === 'string' )
1348+ return assetsURL ( href )
1349+ } ) ,
12851350 }
12861351}
12871352
@@ -1290,12 +1355,23 @@ function assetsURLOfDeps(deps: AssetDeps) {
12901355//
12911356
12921357export type AssetsManifest = {
1293- bootstrapScriptContent : string
1358+ bootstrapScriptContent : string | RuntimeAsset
12941359 clientReferenceDeps : Record < string , AssetDeps >
1295- serverResources ?: Record < string , { css : string [ ] } >
1360+ serverResources ?: Record < string , Pick < AssetDeps , ' css' > >
12961361}
12971362
12981363export type AssetDeps = {
1364+ js : ( string | RuntimeAsset ) [ ]
1365+ css : ( string | RuntimeAsset ) [ ]
1366+ }
1367+
1368+ export type ResolvedAssetsManifest = {
1369+ bootstrapScriptContent : string
1370+ clientReferenceDeps : Record < string , ResolvedAssetDeps >
1371+ serverResources ?: Record < string , Pick < ResolvedAssetDeps , 'css' > >
1372+ }
1373+
1374+ export type ResolvedAssetDeps = {
12991375 js : string [ ]
13001376 css : string [ ]
13011377}
@@ -1574,7 +1650,7 @@ export function vitePluginRscCss(
15741650 this . addWatchFile ( file )
15751651 }
15761652 const hrefs = result . hrefs . map ( ( href ) => assetsURL ( href . slice ( 1 ) ) )
1577- return `export default ${ JSON . stringify ( hrefs ) } `
1653+ return `export default ${ serializeValueWithRuntime ( hrefs ) } `
15781654 }
15791655 } ,
15801656 } ,
@@ -1661,7 +1737,7 @@ export function vitePluginRscCss(
16611737 encodeURIComponent ( importer ) ,
16621738 ]
16631739 const deps = assetsURLOfDeps ( { css : cssHrefs , js : jsHrefs } )
1664- return generateResourcesCode ( JSON . stringify ( deps , null , 2 ) )
1740+ return generateResourcesCode ( serializeValueWithRuntime ( deps ) )
16651741 } else {
16661742 const key = normalizePath ( path . relative ( config . root , importer ) )
16671743 serverResourcesMetaMap [ importer ] = { key }
@@ -1742,7 +1818,10 @@ function collectModuleDependents(mods: EnvironmentModuleNode[]) {
17421818}
17431819
17441820function generateResourcesCode ( depsCode : string ) {
1745- const ResourcesFn = ( React : typeof import ( 'react' ) , deps : AssetDeps ) => {
1821+ const ResourcesFn = (
1822+ React : typeof import ( 'react' ) ,
1823+ deps : ResolvedAssetDeps ,
1824+ ) => {
17461825 return function Resources ( ) {
17471826 return React . createElement ( React . Fragment , null , [
17481827 ...deps . css . map ( ( href : string ) =>
0 commit comments