Skip to content

Commit 6813ad7

Browse files
committed
Handle all component exports
1 parent 14b13b3 commit 6813ad7

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

packages/react-router-dev/vite/rsc/virtual-route-modules.ts

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,44 @@ import * as babel from "../babel";
33
import { parse as esModuleLexer } from "es-module-lexer";
44
import { removeExports } from "../remove-exports";
55

6+
const SERVER_ONLY_COMPONENT_EXPORTS = ["ServerComponent"] as const;
7+
68
const 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+
2144
export const CLIENT_NON_COMPONENT_EXPORTS = [
2245
"clientAction",
2346
"clientLoader",
@@ -37,7 +60,7 @@ function isClientNonComponentExport(
3760

3861
const CLIENT_ROUTE_EXPORTS = [
3962
...CLIENT_NON_COMPONENT_EXPORTS,
40-
...COMPONENT_EXPORTS,
63+
...CLIENT_COMPONENT_EXPORTS,
4164
] as const;
4265
type ClientRouteExport = (typeof CLIENT_ROUTE_EXPORTS)[number];
4366
const 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

Comments
 (0)