@@ -3,21 +3,44 @@ import * as babel from "../babel";
33import { parse as esModuleLexer } from "es-module-lexer" ;
44import { removeExports } from "../remove-exports" ;
55
6+ const SERVER_ONLY_COMPONENT_EXPORTS = [ "ServerComponent" ] as const ;
7+
68const SERVER_ONLY_ROUTE_EXPORTS = [
9+ ...SERVER_ONLY_COMPONENT_EXPORTS ,
710 "loader" ,
811 "action" ,
912 "unstable_middleware" ,
1013 "headers" ,
11- "ServerComponent" ,
1214] as const ;
1315
14- const COMPONENT_EXPORTS = [
15- "default" ,
16+ const COMMON_COMPONENT_EXPORTS = [
1617 "ErrorBoundary" ,
1718 "HydrateFallback" ,
1819 "Layout" ,
1920] as const ;
2021
22+ const SERVER_FIRST_COMPONENT_EXPORTS = [
23+ ...COMMON_COMPONENT_EXPORTS ,
24+ ...SERVER_ONLY_COMPONENT_EXPORTS ,
25+ ] as const ;
26+ type ServerFirstComponentExport =
27+ ( typeof SERVER_FIRST_COMPONENT_EXPORTS ) [ number ] ;
28+ const SERVER_FIRST_COMPONENT_EXPORTS_SET = new Set (
29+ SERVER_FIRST_COMPONENT_EXPORTS ,
30+ ) ;
31+ function isServerFirstComponentExport (
32+ name : string ,
33+ ) : name is ServerFirstComponentExport {
34+ return SERVER_FIRST_COMPONENT_EXPORTS_SET . has (
35+ name as ServerFirstComponentExport ,
36+ ) ;
37+ }
38+
39+ const CLIENT_COMPONENT_EXPORTS = [
40+ ...COMMON_COMPONENT_EXPORTS ,
41+ "default" ,
42+ ] as const ;
43+
2144export const CLIENT_NON_COMPONENT_EXPORTS = [
2245 "clientAction" ,
2346 "clientLoader" ,
@@ -37,7 +60,7 @@ function isClientNonComponentExport(
3760
3861const CLIENT_ROUTE_EXPORTS = [
3962 ...CLIENT_NON_COMPONENT_EXPORTS ,
40- ...COMPONENT_EXPORTS ,
63+ ...CLIENT_COMPONENT_EXPORTS ,
4164] as const ;
4265type ClientRouteExport = ( typeof CLIENT_ROUTE_EXPORTS ) [ number ] ;
4366const CLIENT_ROUTE_EXPORTS_SET = new Set ( CLIENT_ROUTE_EXPORTS ) ;
@@ -90,18 +113,24 @@ async function createVirtualRouteModuleCode({
90113
91114 let code = "" ;
92115 if ( isServerFirstRoute ) {
116+ if ( staticExports . some ( isServerFirstComponentExport ) ) {
117+ code += `import React from "react";\n` ;
118+ }
93119 for ( const staticExport of staticExports ) {
94120 if ( isClientNonComponentExport ( staticExport ) ) {
95121 code += `export { ${ staticExport } } from "${ clientModuleId } ";\n` ;
96- } else if ( staticExport === "ServerComponent" ) {
97- code += `import React from "react";\n` ;
98- code += `import { ServerComponent } from "${ serverModuleId } ";\n` ;
99- code += `export default function ServerComponentWithCss(props) {` ;
100- code += ` return React.createElement(React.Fragment, null, [` ;
101- code += ` import.meta.viteRsc.loadCss(),` ;
102- code += ` React.createElement(ServerComponent, props),` ;
103- code += ` ]);` ;
104- code += `}` ;
122+ } else if (
123+ isServerFirstComponentExport ( staticExport ) &&
124+ // Layout wraps all other exports so doesn't need to have CSS injected
125+ staticExport !== "Layout"
126+ ) {
127+ code += `import { ${ staticExport } as ${ staticExport } WithoutCss } from "${ serverModuleId } ";\n` ;
128+ code += `export ${ staticExport === "ServerComponent" ? "default " : " " } function ${ staticExport } (props) {\n` ;
129+ code += ` return React.createElement(React.Fragment, null,\n` ;
130+ code += ` import.meta.viteRsc.loadCss(),\n` ;
131+ code += ` React.createElement(${ staticExport } WithoutCss, props),\n` ;
132+ code += ` );\n` ;
133+ code += `}\n` ;
105134 } else {
106135 code += `export { ${ staticExport } } from "${ serverModuleId } ";\n` ;
107136 }
@@ -169,7 +198,7 @@ function createVirtualClientRouteModuleCode({
169198 const { staticExports, isServerFirstRoute, hasClientExports } =
170199 parseRouteExports ( routeSource ) ;
171200 const exportsToRemove = isServerFirstRoute
172- ? [ ...SERVER_ONLY_ROUTE_EXPORTS , ...COMPONENT_EXPORTS ]
201+ ? [ ...SERVER_ONLY_ROUTE_EXPORTS , ...CLIENT_COMPONENT_EXPORTS ]
173202 : SERVER_ONLY_ROUTE_EXPORTS ;
174203
175204 const clientRouteModuleAst = babel . parse ( routeSource , {
0 commit comments