@@ -91,47 +91,89 @@ const customServerFile = ({
9191 port,
9292 base,
9393 basename,
94+ templateName,
9495} : {
9596 port : number ;
9697 base ?: string ;
9798 basename ?: string ;
99+ templateName : TemplateName ;
98100} ) => {
99101 base = base ?? "/mybase/" ;
100102 basename = basename ?? base ;
101103
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+ });
116138
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+ });
131172
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+ }
135177} ;
136178
137179test . describe ( "Vite base + React Router basename" , ( ) => {
@@ -280,11 +322,6 @@ test.describe("Vite base + React Router basename", () => {
280322 } ) ;
281323
282324 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-
288325 let port : number ;
289326 let cwd : string ;
290327 let stop : ( ) => void ;
@@ -302,7 +339,7 @@ test.describe("Vite base + React Router basename", () => {
302339 cwd = await createProject (
303340 {
304341 ...( await configFiles ( { port, base, basename, templateName } ) ) ,
305- "server.mjs" : customServerFile ( { port, basename } ) ,
342+ "server.mjs" : customServerFile ( { port, basename, templateName } ) ,
306343 ...sharedFiles ,
307344 } ,
308345 templateName ,
@@ -409,11 +446,6 @@ test.describe("Vite base + React Router basename", () => {
409446 } ) ;
410447
411448 test . describe ( "express build" , async ( ) => {
412- test . skip (
413- templateName . includes ( "rsc" ) ,
414- "Vite build test is already using Express" ,
415- ) ;
416-
417449 let port : number ;
418450 let cwd : string ;
419451 let stop : ( ) => void ;
@@ -435,6 +467,7 @@ test.describe("Vite base + React Router basename", () => {
435467 port,
436468 base,
437469 basename,
470+ templateName,
438471 } ) ,
439472 ...sharedFiles ,
440473 } ,
@@ -480,29 +513,46 @@ test.describe("Vite base + React Router basename", () => {
480513 page,
481514 } ) => {
482515 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+ ) ;
506556
507557 build ( { cwd } ) ;
508558 stop = await customDev ( {
0 commit comments