Skip to content

Commit

Permalink
chore(rsc): Remove Node RSC worker (#11449)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobbe committed Sep 6, 2024
1 parent 1cc6d0a commit aa1e039
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 312 deletions.
14 changes: 6 additions & 8 deletions packages/vite/src/rsc/rscRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { createElement } from 'react'

import { renderToReadableStream } from 'react-server-dom-webpack/server.edge'

import type { ServerAuthState } from '@redwoodjs/auth/dist/AuthProvider/ServerAuthProvider.js'
import { getPaths } from '@redwoodjs/project-config'

import type { RscFetchProps } from '../../../router/src/rsc/ClientRouter.tsx'
Expand All @@ -17,15 +16,14 @@ export type RenderInput = {
props: RscFetchProps | Record<string, unknown>
rsaId?: string | undefined
args?: unknown[] | undefined
serverState: {
headersInit: Record<string, string>
fullUrl: string
serverAuthState: ServerAuthState
}
}

let absoluteClientEntries: Record<string, string> = {}

export function renderRscToStream(input: RenderInput): Promise<ReadableStream> {
return input.rscId ? renderRsc(input) : executeRsa(input)
}

async function loadServerFile(filePath: string) {
console.log('rscRenderer.ts loadServerFile filePath', filePath)
return import(`file://${filePath}`)
Expand Down Expand Up @@ -111,7 +109,7 @@ function getBundlerConfig() {
return bundlerConfig
}

export async function renderRsc(input: RenderInput): Promise<ReadableStream> {
async function renderRsc(input: RenderInput): Promise<ReadableStream> {
if (input.rsaId || !input.args) {
throw new Error(
"Unexpected input. Can't request both RSCs and execute RSAs at the same time.",
Expand Down Expand Up @@ -149,7 +147,7 @@ function isSerializedFormData(data?: unknown): data is SerializedFormData {
return !!data && (data as SerializedFormData)?.__formData__
}

export async function executeRsa(input: RenderInput): Promise<ReadableStream> {
async function executeRsa(input: RenderInput): Promise<ReadableStream> {
console.log('executeRsa input', input)

if (!input.rsaId || !input.args) {
Expand Down
30 changes: 6 additions & 24 deletions packages/vite/src/rsc/rscRequestHandler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Readable } from 'node:stream'

import * as DefaultFetchAPI from '@whatwg-node/fetch'
import { normalizeNodeRequest } from '@whatwg-node/server'
import busboy from 'busboy'
Expand All @@ -10,7 +12,6 @@ import type { HTTPMethod } from 'find-my-way'
import type { ViteDevServer } from 'vite'

import type { RscFetchProps } from '@redwoodjs/router/RscRouter'
import { getAuthState, getRequestHeaders } from '@redwoodjs/server-store'
import type { Middleware } from '@redwoodjs/web/dist/server/middleware'

import {
Expand All @@ -19,10 +20,9 @@ import {
} from '../bundled/react-server-dom-webpack.server.js'
import { hasStatusCode } from '../lib/StatusError.js'
import { invoke } from '../middleware/invokeMiddleware.js'
import { getFullUrlForFlightRequest } from '../utils.js'

import { renderRscToStream } from './rscRenderer.js'
import { sendRscFlightToStudio } from './rscStudioHandlers.js'
import { renderRsc } from './rscWorkerCommunication.js'

const BASE_PATH = '/rw-rsc/'

Expand Down Expand Up @@ -188,27 +188,11 @@ export function createRscRequestHandler(
}

try {
// We construct the URL for the flight request from props
// e.g. http://localhost:8910/rw-rsc/__rwjs__Routes?props=location={pathname:"/about",search:"?foo=bar""}
// becomes http://localhost:8910/about?foo=bar
// In the component, getting location would otherwise be at the rw-rsc URL
const fullUrl = getFullUrlForFlightRequest(req, props)
const readable = await renderRscToStream({ rscId, props, rsaId, args })

const pipeable = renderRsc({
rscId,
props,
rsaId,
args,
// Pass the serverState from server to the worker
// Inside the worker, we'll use this to re-initalize the server state (because workers are stateless)
serverState: {
headersInit: Object.fromEntries(getRequestHeaders().entries()),
serverAuthState: getAuthState(),
fullUrl,
},
})
Readable.fromWeb(readable).pipe(res)

// TODO (RSC): Can we reuse `pipeable` here somehow?
// TODO (RSC): Can we reuse `readable` here somehow?
await sendRscFlightToStudio({
rscId,
props,
Expand All @@ -221,8 +205,6 @@ export function createRscRequestHandler(

// TODO (RSC): See if we can/need to do more error handling here
// pipeable.on(handleError)

pipeable.pipe(res)
} catch (e) {
handleError(e)
}
Expand Down
48 changes: 16 additions & 32 deletions packages/vite/src/rsc/rscStudioHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import http from 'node:http'
import type { PassThrough } from 'node:stream'
import type { ReadableStream } from 'node:stream/web'

import type { Request } from 'express'

import { getConfig, getRawConfig } from '@redwoodjs/project-config'
import { getAuthState, getRequestHeaders } from '@redwoodjs/server-store'

import { getFullUrlForFlightRequest } from '../utils.js'

import { renderRscToStream } from './rscRenderer.js'
import type { RenderInput } from './rscRenderer.js'
import { renderRsc } from './rscWorkerCommunication.js'

const isTest = () => {
return process.env.NODE_ENV === 'test'
Expand All @@ -36,24 +33,21 @@ const getStudioPort = () => {
}

const processRenderRscStream = async (
pipeable: PassThrough,
readable: ReadableStream,
): Promise<string> => {
return new Promise((resolve, reject) => {
const chunks = [] as any

pipeable.on('data', (chunk: any) => {
chunks.push(chunk)
})
const chunks: Uint8Array[] = []

pipeable.on('end', () => {
const resultBuffer = Buffer.concat(chunks)
const resultString = resultBuffer.toString('utf-8')
resolve(resultString)
const writable = new WritableStream({
write(chunk) {
chunks.push(chunk)
},
close() {
resolve(Buffer.concat(chunks).toString('utf8'))
},
})

pipeable.on('error', (error) => {
reject(error)
})
readable.pipeTo(writable).catch((error) => reject(error))
})
}

Expand Down Expand Up @@ -100,11 +94,11 @@ const postFlightToStudio = (payload: string, metadata: Record<string, any>) => {
}

const createStudioFlightHandler = (
pipeable: PassThrough,
readable: ReadableStream,
metadata: Record<string, any>,
) => {
if (shouldSendToStudio()) {
processRenderRscStream(pipeable)
processRenderRscStream(readable)
.then((payload) => {
console.debug('Sending RSC Rendered stream to Studio')
postFlightToStudio(payload, metadata)
Expand Down Expand Up @@ -136,21 +130,11 @@ export const sendRscFlightToStudio = async (input: StudioRenderInput) => {
const startedAt = Date.now()
const start = performance.now()

// We construct the URL for the flight request from props
// e.g. http://localhost:8910/rw-rsc/__rwjs__Routes?props=location={pathname:"/about",search:"?foo=bar""}
// becomes http://localhost:8910/about?foo=bar
const fullUrl = getFullUrlForFlightRequest(req, props)

const pipeable = renderRsc({
const readable = await renderRscToStream({
rscId,
props,
rsaId,
args,
serverState: {
headersInit: Object.fromEntries(getRequestHeaders().entries()),
serverAuthState: getAuthState(),
fullUrl,
},
})
const endedAt = Date.now()
const end = performance.now()
Expand Down Expand Up @@ -178,7 +162,7 @@ export const sendRscFlightToStudio = async (input: StudioRenderInput) => {
}

// send rendered request to Studio
createStudioFlightHandler(pipeable as PassThrough, metadata)
createStudioFlightHandler(readable, metadata)
} catch (e) {
if (e instanceof Error) {
console.error('An error occurred rendering RSC and sending to Studio:', e)
Expand Down
114 changes: 0 additions & 114 deletions packages/vite/src/rsc/rscWorker.ts

This file was deleted.

Loading

0 comments on commit aa1e039

Please sign in to comment.