@@ -91,47 +91,89 @@ const customServerFile = ({
91
91
port,
92
92
base,
93
93
basename,
94
+ templateName,
94
95
} : {
95
96
port : number ;
96
97
base ?: string ;
97
98
basename ?: string ;
99
+ templateName : TemplateName ;
98
100
} ) => {
99
101
base = base ?? "/mybase/" ;
100
102
basename = basename ?? base ;
101
103
102
- return js `
103
- import { createRequestHandler } from "@react-router/express";
104
- import express from "express";
105
-
106
- const viteDevServer =
107
- process.env.NODE_ENV === "production"
108
- ? undefined
109
- : await import("vite").then(({ createServer }) =>
110
- createServer({
111
- server: {
112
- middlewareMode: true,
113
- },
114
- })
115
- );
104
+ if ( templateName . includes ( "rsc" ) ) {
105
+ return js `
106
+ import { createRequestListener } from "@mjackson/node-fetch-server";
107
+ import express from "express";
108
+
109
+ const viteDevServer =
110
+ process.env.NODE_ENV === "production"
111
+ ? undefined
112
+ : await import("vite").then(({ createServer }) =>
113
+ createServer({
114
+ server: {
115
+ middlewareMode: true,
116
+ },
117
+ })
118
+ );
119
+
120
+ const requestListener = viteDevServer
121
+ ? async (req, res) => {
122
+ // In dev mode, ensure we load a fresh request handler every request
123
+ const rscEntry = await viteDevServer.environments.rsc.runner.import(
124
+ "virtual:react-router/unstable_rsc/rsc-entry",
125
+ );
126
+ return createRequestListener(rscEntry.default)(req, res);
127
+ }
128
+ // In production, get the static request handler from the build output
129
+ : createRequestListener((await import("./build/server/index.js")).default);
130
+
131
+ const app = express();
132
+ app.use("${ base } ", viteDevServer?.middlewares || express.static("build/client"));
133
+ app.all("${ basename } *", requestListener);
134
+ app.get("*", (_req, res) => {
135
+ res.setHeader("content-type", "text/html")
136
+ res.end('React Router app is at <a href="${ basename } ">${ basename } </a>');
137
+ });
116
138
117
- const app = express();
118
- app.use("${ base } ", viteDevServer?.middlewares || express.static("build/client"));
119
- app.all(
120
- "${ basename } *",
121
- createRequestHandler({
122
- build: viteDevServer
123
- ? () => viteDevServer.ssrLoadModule("virtual:react-router/server-build")
124
- : await import("./build/server/index.js"),
125
- })
126
- );
127
- app.get("*", (_req, res) => {
128
- res.setHeader("content-type", "text/html")
129
- res.end('React Router app is at <a href="${ basename } ">${ basename } </a>');
130
- });
139
+ const port = ${ port } ;
140
+ app.listen(port, () => console.log('http://localhost:' + port));
141
+ ` ;
142
+ } else {
143
+ return js `
144
+ import { createRequestHandler } from "@react-router/express";
145
+ import express from "express";
146
+
147
+ const viteDevServer =
148
+ process.env.NODE_ENV === "production"
149
+ ? undefined
150
+ : await import("vite").then(({ createServer }) =>
151
+ createServer({
152
+ server: {
153
+ middlewareMode: true,
154
+ },
155
+ })
156
+ );
157
+
158
+ const app = express();
159
+ app.use("${ base } ", viteDevServer?.middlewares || express.static("build/client"));
160
+ app.all(
161
+ "${ basename } *",
162
+ createRequestHandler({
163
+ build: viteDevServer
164
+ ? () => viteDevServer.ssrLoadModule("virtual:react-router/server-build")
165
+ : await import("./build/server/index.js"),
166
+ })
167
+ );
168
+ app.get("*", (_req, res) => {
169
+ res.setHeader("content-type", "text/html")
170
+ res.end('React Router app is at <a href="${ basename } ">${ basename } </a>');
171
+ });
131
172
132
- const port = ${ port } ;
133
- app.listen(port, () => console.log('http://localhost:' + port));
134
- ` ;
173
+ const port = ${ port } ;
174
+ app.listen(port, () => console.log('http://localhost:' + port));
175
+ ` ;
176
+ }
135
177
} ;
136
178
137
179
test . describe ( "Vite base + React Router basename" , ( ) => {
@@ -280,11 +322,6 @@ test.describe("Vite base + React Router basename", () => {
280
322
} ) ;
281
323
282
324
test . describe ( "express dev" , async ( ) => {
283
- test . skip (
284
- templateName . includes ( "rsc" ) ,
285
- "RSC Framework Mode doesn't support Vite middleware mode yet" ,
286
- ) ;
287
-
288
325
let port : number ;
289
326
let cwd : string ;
290
327
let stop : ( ) => void ;
@@ -302,7 +339,7 @@ test.describe("Vite base + React Router basename", () => {
302
339
cwd = await createProject (
303
340
{
304
341
...( await configFiles ( { port, base, basename, templateName } ) ) ,
305
- "server.mjs" : customServerFile ( { port, basename } ) ,
342
+ "server.mjs" : customServerFile ( { port, basename, templateName } ) ,
306
343
...sharedFiles ,
307
344
} ,
308
345
templateName ,
@@ -409,11 +446,6 @@ test.describe("Vite base + React Router basename", () => {
409
446
} ) ;
410
447
411
448
test . describe ( "express build" , async ( ) => {
412
- test . skip (
413
- templateName . includes ( "rsc" ) ,
414
- "Vite build test is already using Express" ,
415
- ) ;
416
-
417
449
let port : number ;
418
450
let cwd : string ;
419
451
let stop : ( ) => void ;
@@ -435,6 +467,7 @@ test.describe("Vite base + React Router basename", () => {
435
467
port,
436
468
base,
437
469
basename,
470
+ templateName,
438
471
} ) ,
439
472
...sharedFiles ,
440
473
} ,
@@ -480,29 +513,46 @@ test.describe("Vite base + React Router basename", () => {
480
513
page,
481
514
} ) => {
482
515
port = await getPort ( ) ;
483
- cwd = await createProject ( {
484
- ...( await configFiles ( {
485
- templateName,
486
- port,
487
- base : "https://cdn.example.com/assets/" ,
488
- basename : "/app/" ,
489
- } ) ) ,
490
- // Slim server that only serves basename (route) requests from the React Router handler
491
- "server.mjs" : String . raw `
492
- import { createRequestHandler } from "@react-router/express";
493
- import express from "express";
494
-
495
- const app = express();
496
- app.all(
497
- "/app/*",
498
- createRequestHandler({ build: await import("./build/server/index.js") })
499
- );
500
-
501
- const port = ${ port } ;
502
- app.listen(port, () => console.log('http://localhost:' + port));
503
- ` ,
504
- ...sharedFiles ,
505
- } ) ;
516
+ cwd = await createProject (
517
+ {
518
+ ...( await configFiles ( {
519
+ templateName,
520
+ port,
521
+ base : "https://cdn.example.com/assets/" ,
522
+ basename : "/app/" ,
523
+ } ) ) ,
524
+ // Slim server that only serves basename (route) requests from the React Router handler
525
+ "server.mjs" : templateName . includes ( "rsc" )
526
+ ? String . raw `
527
+ import { createRequestListener } from "@mjackson/node-fetch-server";
528
+ import express from "express";
529
+
530
+ const app = express();
531
+ app.all(
532
+ "/app/*",
533
+ createRequestListener((await import("./build/server/index.js")).default)
534
+ );
535
+
536
+ const port = ${ port } ;
537
+ app.listen(port, () => console.log('http://localhost:' + port));
538
+ `
539
+ : String . raw `
540
+ import { createRequestHandler } from "@react-router/express";
541
+ import express from "express";
542
+
543
+ const app = express();
544
+ app.all(
545
+ "/app/*",
546
+ createRequestHandler({ build: await import("./build/server/index.js") })
547
+ );
548
+
549
+ const port = ${ port } ;
550
+ app.listen(port, () => console.log('http://localhost:' + port));
551
+ ` ,
552
+ ...sharedFiles ,
553
+ } ,
554
+ templateName ,
555
+ ) ;
506
556
507
557
build ( { cwd } ) ;
508
558
stop = await customDev ( {
0 commit comments