Skip to content

Commit

Permalink
RSC: Make code and execution easier to follow. Improve error handling. (
Browse files Browse the repository at this point in the history
#9154)

1. Add code comments to make the code easier to follow
2. Add console logs to make execution easier to follow
3. Add custom Error to improve error handling
  • Loading branch information
Tobbe authored Sep 11, 2023
1 parent ee334bc commit d3475cd
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 9 deletions.
3 changes: 3 additions & 0 deletions packages/vite/src/buildRscFeServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ export const buildRscFeServer = async ({
webDistEntries,
webRouteManifest,
}: Args) => {
// Step 1: Analyze all files and generate a list of RSCs and RSFs
const { clientEntryFiles, serverEntryFiles } = await rscBuild(viteConfigPath)

// Step 2: Generate the client bundle
const clientBuildOutput = await viteBuild({
// configFile: viteConfigPath,
root: webSrc,
Expand Down Expand Up @@ -64,6 +66,7 @@ export const buildRscFeServer = async ({
throw new Error('Unexpected vite client build output')
}

// Step 3: Generate the server output
const serverBuildOutput = await serverBuild(
entries,
clientEntryFiles,
Expand Down
29 changes: 25 additions & 4 deletions packages/vite/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ import type { ReactElement } from 'react'

import { createFromFetch, encodeReply } from 'react-server-dom-webpack/client'

import { StatusError } from './lib/StatusError'

const checkStatus = async (
responsePromise: Promise<Response>
): Promise<Response> => {
const response = await responsePromise

if (!response.ok) {
throw new StatusError(response.statusText, response.status)
}

return response
}

export function serve<Props>(rscId: string, basePath = '/RSC/') {
type SetRerender = (
rerender: (next: [ReactElement, string]) => void
Expand All @@ -24,24 +38,30 @@ export function serve<Props>(rscId: string, basePath = '/RSC/') {

const options = {
async callServer(rsfId: string, args: unknown[]) {
console.log('client.ts :: callServer rsfId', rsfId, 'args', args)
const isMutating = !!mutationMode
const searchParams = new URLSearchParams()
searchParams.set('action_id', rsfId)
let id: string

if (isMutating) {
id = rscId
searchParams.set('props', serializedProps)
} else {
id = '_'
}

const response = fetch(basePath + id + '/' + searchParams, {
method: 'POST',
body: await encodeReply(args),
})

const data = createFromFetch(response, options)

if (isMutating) {
rerender?.([data, serializedProps])
}

return data
},
}
Expand All @@ -54,11 +74,12 @@ export function serve<Props>(rscId: string, basePath = '/RSC/') {
'fetchRSC before createFromFetch',
basePath + rscId + '/' + searchParams
)
const data = createFromFetch(
prefetched || fetch(basePath + rscId + '/' + searchParams),
options
)

const response =
prefetched || fetch(basePath + rscId + '/' + searchParams)
const data = createFromFetch(checkStatus(response), options)
console.log('fetchRSC after createFromFetch. data:', data)

return [data, setRerender]
}
)
Expand Down
5 changes: 5 additions & 0 deletions packages/vite/src/lib/StatusError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class StatusError extends Error {
constructor(message: string, public statusCode: number) {
super(message)
}
}
2 changes: 1 addition & 1 deletion packages/vite/src/rscBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { onWarn } from './lib/onWarn'
import { rscAnalyzePlugin } from './waku-lib/vite-plugin-rsc'

/**
* RSC build
* RSC build. Step 1 of 3.
* Uses rscAnalyzePlugin to collect client and server entry points
* Starts building the AST in entries.ts
* Doesn't output any files, only collects a list of RSCs and RSFs
Expand Down
6 changes: 5 additions & 1 deletion packages/vite/src/waku-lib/rsc-handler-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createServer } from 'vite'
import { getPaths } from '@redwoodjs/project-config'

import type { defineEntries } from '../entries'
import { StatusError } from '../lib/StatusError'
// import type { unstable_GetCustomModules } from '../waku-server'

import { configFileConfig, resolveConfig } from './config'
Expand Down Expand Up @@ -226,7 +227,8 @@ const getFunctionComponent = async (
if (typeof mod?.default === 'function') {
return mod?.default
}
throw new Error('No function component found')
// TODO (RSC): Making this a 404 error is marked as "HACK" in waku's source
throw new StatusError('No function component found', 404)
}

let absoluteClientEntries: Record<string, string> = {}
Expand Down Expand Up @@ -287,6 +289,8 @@ export async function renderRSC(input: RenderInput): Promise<PipeableStream> {
}
)

console.log('renderRSC input', input)

if (input.rsfId && input.args) {
const [fileId, name] = input.rsfId.split('#')
const fname = path.join(config.root, fileId)
Expand Down
8 changes: 6 additions & 2 deletions packages/vite/src/waku-lib/rsc-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ import('${moduleId}');`
}

// HACK Patching stream is very fragile.
export const transformRsfId = (prefixToRemove: string) =>
new Transform({
export const transformRsfId = (prefixToRemove: string) => {
console.log('prefixToRemove', prefixToRemove)

return new Transform({
transform(chunk, encoding, callback) {
if (encoding !== ('buffer' as any)) {
throw new Error('Unknown encoding')
}
const data = chunk.toString()
const lines = data.split('\n')
console.log('lines', lines)
let changed = false
for (let i = 0; i < lines.length; ++i) {
const match = lines[i].match(
Expand All @@ -77,3 +80,4 @@ export const transformRsfId = (prefixToRemove: string) =>
callback(null, changed ? Buffer.from(lines.join('\n')) : chunk)
},
})
}
4 changes: 3 additions & 1 deletion packages/vite/src/waku-lib/vite-plugin-rsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { ResolveFunction } from '../react-server-dom-webpack/node-loader'

import { codeToInject } from './rsc-utils.js'

// Used in Step 2 of the build process, for the client bundle
export function rscIndexPlugin(): Plugin {
return {
name: 'rsc-index-plugin',
Expand Down Expand Up @@ -118,6 +119,7 @@ export function rscReloadPlugin(fn: (type: 'full-reload') => void): Plugin {
}
return false
}

return {
name: 'reload-plugin',
configResolved(config) {
Expand All @@ -144,7 +146,7 @@ export function rscAnalyzePlugin(
serverEntryCallback: (id: string) => void
): Plugin {
return {
name: 'rsc-bundle-plugin',
name: 'rsc-analyze-plugin',
transform(code, id) {
const ext = path.extname(id)
if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
Expand Down

0 comments on commit d3475cd

Please sign in to comment.