wingleung / remix-aws

AWS adapter for Remix
https://www.npmjs.com/package/remix-aws
MIT License
23 stars 5 forks source link

Add response streaming support for Lambda #10

Open moltar opened 7 months ago

moltar commented 7 months ago

Almost a year ago now, AWS introduced response streaming:

https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/

This works great with CloudFront <- Lambda URL setup, as both support response streaming.

This, however, does not work with API Gateways and ALB yet, and supposedly it is coming later.

Here's a quick PoC I made a while back for streaming pure React code from a Lambda handler. Not sure if this is comprehensive, this was just a quick PoC.

import type { APIGatewayProxyEventV2, Context } from 'aws-lambda';
import { streamifyResponse, ResponseStream } from 'lambda-stream';
import React from 'react';
import { renderToPipeableStream } from 'react-dom/server';
import { App } from './app';

export const handler = async (event: APIGatewayProxyEventV2, stream: ResponseStream, ctx: Context) => {
  stream.setContentType('text/html');

  const { pipe, abort } = renderToPipeableStream(App(event.rawPath), {
    onShellReady() {
      pipe(stream);
    },
    onAllReady() {
      stream.end();
    },
  });

  // https://react.dev/reference/react-dom/server/renderToPipeableStream#aborting-server-rendering
  setTimeout(() => abort(), ctx.getRemainingTimeInMillis() - 500);
};

streamifyResponse(handler);

Where App is:

export function App(path: string) {
  return (
      <html>
        <head>
          <title>App</title>
        </head>
        <body>
            <div>hello</div>
        </body>
      </html>
  );
}
wingleung commented 6 months ago

Thanks for kickstarting this 👍 There's a couple of things a developer should setup to be able to use streaming in remix 👉 https://remix.run/docs/en/main/guides/streaming

If they did that, we would probably need to (optionally) turn our sendRemixResponse into streams. The nodeResponse.body is already a readable stream so I think we could something similar to this https://github.com/remix-run/remix/blob/dev/packages/remix-dev/config/defaults/entry.server.node.tsx#L72C11-L72C65

very interesting!

moltar commented 6 months ago

I think we could something similar

That's the default server impl btw.

wingleung commented 5 months ago

idd, what I'm trying to get at is how we should tackle this

Solution 1: let developer set up streaming in entry.server.ts and try and find a way to pipe the stream in our adapter Solution 2: do streaming ourselves in sendRemixResponse and/or here