I'm not sure if this a bug per-se, but I encountered a Worker runtime behavior that wasn't reproducible in Miniflare.
tl;dr Using TransformStream will often trigger a runtime error: "The script will never generate a response"
My workers library, Keywork, has a JSXResponse
class that accepts some React JSX and returns an instance of Response
. This works fine when the JSX is first rendered to a string and then fed to Response's body, since this is really just a convenience wrapper around a few functions:
const app = new WorkerRouter()
app.get('/', () => {
return new JSXResponse(
<div>
<h1>Look! I'm rendering JSX</h1>
</div>
)
})
However, refactoring JSXResponse
to use React's streaming renderer was not so obvious. JS constructors must be synchronous, and renderToReadableStream
is async.
Ideally, a Keywork developer wouldn't have to change their code to take advantage of streaming. So, being the very clever web developer I am, I wrote something like this:
class JSXResponse extends Response {
constructor(jsx: React.ReactElement, ...omittedArgs: any[]) {
const passThroughStream = new TransformStream()
super(passThroughStream.readable)
pipeReactRenderToStream(passThroughStream, jsx)
}
}
function pipeReactRenderToStream(passThroughStream: TransformStream, jsx: React.ReactElement) {
const readableStreamFromReact = await renderToReadableStream(jsx)
readableStreamFromReact.pipeTo(passThroughStream.writable)
}
This works fine in Miniflare, but throws an exception once deployed: "The script will never generate a response."
Maybe it's the case that the Workers runtime isn't checking if TransformStream
is still pending. I couldn't find an example of this behavior on the docs or in Discord, so this might help if someone else later runs into this bug