@@ -106,6 +106,9 @@ function resolvePackage(name: string) {
106106
107107export type { RscPluginManager }
108108
109+ /**
110+ * @experimental
111+ */
109112class RscPluginManager {
110113 server ! : ViteDevServer
111114 config ! : ResolvedConfig
@@ -127,6 +130,21 @@ class RscPluginManager {
127130 toRelativeId ( id : string ) : string {
128131 return normalizePath ( path . relative ( this . config . root , id ) )
129132 }
133+
134+ writeAssetsManifest ( environmentNames : string [ ] ) : void {
135+ // write client manifest to all non-client builds during post-build step.
136+ // this makes each server build to be self-contained and deploy-able for cloudflare.
137+ const assetsManifestCode = `export default ${ serializeValueWithRuntime (
138+ this . buildAssetsManifest ,
139+ ) } `
140+ for ( const name of environmentNames ) {
141+ const manifestPath = path . join (
142+ this . config . environments [ name ] ! . build . outDir ,
143+ BUILD_ASSETS_MANIFEST_NAME ,
144+ )
145+ fs . writeFileSync ( manifestPath , assetsManifestCode )
146+ }
147+ }
130148}
131149
132150export type RscPluginOptions = {
@@ -186,6 +204,14 @@ export type RscPluginOptions = {
186204 */
187205 useBuildAppHook ?: boolean
188206
207+ /**
208+ * Skip the default buildApp orchestration and expose utilities on `builder.rsc`
209+ * for downstream frameworks to implement custom build pipelines.
210+ * @experimental
211+ * @default false
212+ */
213+ customBuildApp ?: boolean
214+
189215 /**
190216 * Custom environment configuration
191217 * @experimental
@@ -343,7 +369,7 @@ export default function vitePluginRsc(
343369 manager . stabilize ( )
344370 logStep ( '[4/4] build client environment...' )
345371 await builder . build ( builder . environments . client ! )
346- writeAssetsManifest ( [ 'rsc' ] )
372+ manager . writeAssetsManifest ( [ 'rsc' ] )
347373 return
348374 }
349375
@@ -399,27 +425,23 @@ export default function vitePluginRsc(
399425 fs . renameSync ( tempRscOutDir , rscOutDir )
400426 }
401427
402- writeAssetsManifest ( [ 'ssr' , 'rsc' ] )
403- }
404-
405- function writeAssetsManifest ( environmentNames : string [ ] ) {
406- // output client manifest to non-client build directly.
407- // this makes server build to be self-contained and deploy-able for cloudflare.
408- const assetsManifestCode = `export default ${ serializeValueWithRuntime (
409- manager . buildAssetsManifest ,
410- ) } `
411- for ( const name of environmentNames ) {
412- const manifestPath = path . join (
413- manager . config . environments [ name ] ! . build . outDir ,
414- BUILD_ASSETS_MANIFEST_NAME ,
415- )
416- fs . writeFileSync ( manifestPath , assetsManifestCode )
417- }
428+ manager . writeAssetsManifest ( [ 'ssr' , 'rsc' ] )
418429 }
419430
420431 let hasReactServerDomWebpack = false
421432
422433 return [
434+ {
435+ name : 'rsc:builder-api' ,
436+ buildApp : {
437+ order : 'pre' as const ,
438+ async handler ( builder ) {
439+ builder . rsc = {
440+ manager,
441+ }
442+ } ,
443+ } ,
444+ } ,
423445 {
424446 name : 'rsc' ,
425447 async config ( config , env ) {
@@ -539,15 +561,17 @@ export default function vitePluginRsc(
539561 } ,
540562 } ,
541563 } ,
542- builder : {
543- sharedPlugins : true ,
544- sharedConfigBuild : true ,
545- async buildApp ( builder ) {
546- if ( ! rscPluginOptions . useBuildAppHook ) {
547- await buildApp ( builder )
548- }
549- } ,
550- } ,
564+ builder : rscPluginOptions . customBuildApp
565+ ? undefined
566+ : {
567+ sharedPlugins : true ,
568+ sharedConfigBuild : true ,
569+ async buildApp ( builder ) {
570+ if ( ! rscPluginOptions . useBuildAppHook ) {
571+ await buildApp ( builder )
572+ }
573+ } ,
574+ } ,
551575 }
552576 } ,
553577 configResolved ( ) {
@@ -557,6 +581,9 @@ export default function vitePluginRsc(
557581 } ,
558582 buildApp : {
559583 async handler ( builder ) {
584+ if ( rscPluginOptions . customBuildApp ) {
585+ return
586+ }
560587 if ( rscPluginOptions . useBuildAppHook ) {
561588 await buildApp ( builder )
562589 }
0 commit comments