@@ -23,6 +23,7 @@ import { createMiddlewareRouter } from './middleware/register.js'
23
23
import { rscRoutesAutoLoader } from './plugins/vite-plugin-rsc-routes-auto-loader.js'
24
24
import { rscRoutesImports } from './plugins/vite-plugin-rsc-routes-imports.js'
25
25
import { rscSsrRouterImport } from './plugins/vite-plugin-rsc-ssr-router-import.js'
26
+ import { rscTransformUseServerPlugin } from './plugins/vite-plugin-rsc-transform-server.js'
26
27
import { createWebSocketServer } from './rsc/rscWebSocketServer.js'
27
28
import { collectCssPaths , componentsModules } from './streaming/collectCss.js'
28
29
import { createReactStreamingHandler } from './streaming/createReactStreamingHandler.js'
@@ -183,6 +184,7 @@ async function createServer() {
183
184
globalThis . __rwjs__vite_ssr_runtime =
184
185
await createViteRuntime ( viteSsrDevServer )
185
186
globalThis . __rwjs__client_references = new Set < string > ( )
187
+ globalThis . __rwjs__server_references = new Set < string > ( )
186
188
187
189
// const clientEntryFileSet = new Set<string>()
188
190
// const serverEntryFileSet = new Set<string>()
@@ -258,7 +260,23 @@ async function createServer() {
258
260
'busboy' ,
259
261
'cookie' ,
260
262
] ,
261
- // exclude: ['webpack']
263
+ // Without excluding `util` we get "TypeError: util.TextEncoder is not
264
+ // a constructor" in react-server-dom-webpack.server because it'll try
265
+ // to use Browserify's `util` instead of Node's. And Browserify's
266
+ // polyfill is missing TextEncoder+TextDecoder. The reason it's using
267
+ // the Browserify polyfill is because we have
268
+ // `vite-plugin-node-polyfills` as a dependency, and that'll add
269
+ // Browserify's `node-util` to `node_modules`, so when Vite goes to
270
+ // resolve `import { TextEncoder } from 'util` it'll find the one in
271
+ // `node_modules` instead of Node's internal version.
272
+ // We only see this in dev, and not in prod. I'm not entirely sure why
273
+ // but I have two guesses: 1. When RSC is enabled we don't actually use
274
+ // `vite-plugin-node-polyfill`, so some kind of tree shaking is
275
+ // happening, which prevents the issue from occurring. 2. In prod we
276
+ // only use Node's dependency resolution. Vite is not involved. And
277
+ // that difference in resolution is what prevents the issue from
278
+ // occurring.
279
+ exclude : [ 'util' ] ,
262
280
} ,
263
281
} ,
264
282
resolve : {
@@ -268,6 +286,10 @@ async function createServer() {
268
286
{
269
287
name : 'rsc-record-and-tranform-use-client-plugin' ,
270
288
transform ( code , id , _options ) {
289
+ // This is called from `getRoutesComponent()` in `clientSsr.ts`
290
+ // during SSR. So options.ssr will be true in that case.
291
+ // TODO (RSC): When is this called outside of SSR?
292
+
271
293
// TODO (RSC): We need to make sure this `id` always matches what
272
294
// vite uses
273
295
globalThis . __rwjs__client_references ?. delete ( id )
@@ -312,6 +334,7 @@ async function createServer() {
312
334
return { code : result , map : null }
313
335
} ,
314
336
} ,
337
+ rscTransformUseServerPlugin ( '' , { } ) ,
315
338
316
339
// The rscTransformUseClientPlugin maps paths like
317
340
// /Users/tobbe/.../rw-app/node_modules/@tobbe.dev/rsc-test/dist/rsc-test.es.js
@@ -348,7 +371,8 @@ async function createServer() {
348
371
// },
349
372
} ,
350
373
appType : 'custom' ,
351
- cacheDir : './node_modules/.vite-rsc' ,
374
+ // Using a unique cache dir here to not clash with our other vite server
375
+ cacheDir : '../node_modules/.vite-rsc' ,
352
376
} )
353
377
354
378
globalThis . __rwjs__vite_rsc_runtime = await createViteRuntime ( viteRscServer )
0 commit comments