Skip to content

Instantly share code, notes, and snippets.

@GirlBossRush
Created July 21, 2022 21:09
Show Gist options
  • Save GirlBossRush/5ba008de2b6865f705d5bee5705db1b0 to your computer and use it in GitHub Desktop.
Save GirlBossRush/5ba008de2b6865f705d5bee5705db1b0 to your computer and use it in GitHub Desktop.
Cloudflare Workers and TransformStream: "The script will never generate a response"

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment