@@ -155,19 +155,24 @@ export const DEFAULT_OPTIMIZE_PACKAGES: string[] = [
155155
156156/**
157157 * Resolve a package.json exports value to a string entry path.
158- * Prefers react-server → node → import → module → default conditions, recursing into
159- * nested objects. The "react-server" condition is checked first because this plugin
160- * targets RSC/SSR environments where packages like `react` and `react-dom` expose
161- * RSC-compatible entry points under that condition.
158+ * Prefers node → import → module → default conditions, recursing into nested objects.
159+ * When `preferReactServer` is true (RSC environment), "react-server" is checked first
160+ * so that packages like `react` and `react-dom` resolve their RSC-compatible entry points.
162161 */
163- function resolveExportsValue ( value : ExportsValue ) : string | null {
162+ function resolveExportsValue ( value : ExportsValue , preferReactServer : boolean ) : string | null {
164163 if ( typeof value === "string" ) return value ;
165164 if ( typeof value === "object" && value !== null ) {
166- // Prefer ESM conditions in order; "react-server" first for RSC/SSR environments
167- for ( const key of [ "react-server" , "node" , "import" , "module" , "default" ] ) {
165+ // In the RSC environment prefer "react-server" before standard conditions so that
166+ // packages exposing RSC-only entry points (e.g. react, react-dom) are resolved
167+ // to their server-compatible barrel. In the SSR environment the "react-server"
168+ // condition must NOT be preferred — SSR renders with the full React runtime.
169+ const conditions = preferReactServer
170+ ? [ "react-server" , "node" , "import" , "module" , "default" ]
171+ : [ "node" , "import" , "module" , "default" ] ;
172+ for ( const key of conditions ) {
168173 const nested = value [ key ] ;
169174 if ( nested !== undefined ) {
170- const resolved = resolveExportsValue ( nested ) ;
175+ const resolved = resolveExportsValue ( nested , preferReactServer ) ;
171176 if ( resolved ) return resolved ;
172177 }
173178 }
@@ -231,8 +236,14 @@ function resolvePackageInfo(packageName: string, projectRoot: string): PackageIn
231236/**
232237 * Resolve a package name to its ESM entry file path.
233238 * Checks `exports["."]` → `module` → `main`, then falls back to require.resolve.
239+ * Pass `preferReactServer: true` in the RSC environment to prefer the "react-server"
240+ * export condition over "node"/"import" when resolving the barrel entry.
234241 */
235- function resolvePackageEntry ( packageName : string , projectRoot : string ) : string | null {
242+ function resolvePackageEntry (
243+ packageName : string ,
244+ projectRoot : string ,
245+ preferReactServer : boolean ,
246+ ) : string | null {
236247 try {
237248 const info = resolvePackageInfo ( packageName , projectRoot ) ;
238249 if ( ! info ) return null ;
@@ -244,7 +255,7 @@ function resolvePackageEntry(packageName: string, projectRoot: string): string |
244255 // the barrel entry point, not individual sub-module paths.
245256 const dotExport = pkgJson . exports [ "." ] ;
246257 if ( dotExport ) {
247- const entryPath = resolveExportsValue ( dotExport ) ;
258+ const entryPath = resolveExportsValue ( dotExport , preferReactServer ) ;
248259 if ( entryPath ) {
249260 return path . resolve ( pkgDir , entryPath ) . split ( path . sep ) . join ( "/" ) ;
250261 }
@@ -545,6 +556,9 @@ export function createOptimizeImportsPlugin(
545556 // dep optimizer which handles barrel imports correctly.
546557 const env = ( this as { environment ?: { name ?: string } } ) . environment ;
547558 if ( env ?. name === "client" ) return null ;
559+ // "react-server" export condition should only be preferred in the RSC environment.
560+ // SSR renders with the full React runtime and must NOT resolve react-server entries.
561+ const preferReactServer = env ?. name === "rsc" ;
548562 // Skip virtual modules
549563 if ( id . startsWith ( "\0" ) ) return null ;
550564
@@ -580,10 +594,14 @@ export function createOptimizeImportsPlugin(
580594
581595 // Build or retrieve the barrel export map for this package.
582596 // Cache the resolved entry path to avoid repeated FS work.
583- let barrelEntry : string | null | undefined = entryPathCache . get ( importSource ) ;
597+ // The cache key includes the environment prefix because RSC resolves the
598+ // "react-server" export condition while SSR uses the standard conditions —
599+ // the same package can have different barrel entry paths in each environment.
600+ const cacheKey = `${ preferReactServer ? "rsc" : "ssr" } :${ importSource } ` ;
601+ let barrelEntry : string | null | undefined = entryPathCache . get ( cacheKey ) ;
584602 if ( barrelEntry === undefined ) {
585- barrelEntry = resolvePackageEntry ( importSource , root ) ;
586- entryPathCache . set ( importSource , barrelEntry ) ;
603+ barrelEntry = resolvePackageEntry ( importSource , root , preferReactServer ) ;
604+ entryPathCache . set ( cacheKey , barrelEntry ) ;
587605 }
588606 const exportMap = buildBarrelExportMap (
589607 importSource ,
0 commit comments