resend / react-email

💌 Build and send emails using React
https://react.email
MIT License
12.67k stars 583 forks source link

feat(render): Add renderAsync function to enable edge runtime support #603

Closed mkreuzmayr closed 1 year ago

mkreuzmayr commented 1 year ago

closes https://github.com/resendlabs/react-email/issues/493

My implementation checks if renderToStaticMarkup is defined. If not renderToReadableStream is used and the stream is converted to a string.

It would be nice to have something like this directly integrated in react-email, but it requires the introduction of an async function like renderAsync to work, so we are not introducing a breaking change for the render function. I could create a pull request with my changes and add it to the docs if you are ok with creating a renderAsync function.

bukinoshita commented 1 year ago

Do we have a working example of this running on Vercel edge? Would be better to test.

thosmos commented 1 year ago

This is an implementation that uses ReactDOMServer.ReactDOMServerReadableStream and that also has been tested on a production Vercel Nextjs edge API function:

const streamToString = async (stream: ReactDOMServer.ReactDOMServerReadableStream): Promise<string> => {
  const reader = stream.getReader();
  const decoder = new TextDecoder();
  let result = '';
  while (true) {
    const { done, value } = await reader.read();
    if (done) return result;
    result += decoder.decode(value);
  }
};
mkreuzmayr commented 1 year ago

@bukinoshita I built a small example with a preview (in plain-text) and apple-receipt endpoint using serverless and edge functions and deployed it on Vercel.

https://github.com/mkreuzmayr/react-email-edge

Endpoints

Preview (plain-text)

https://react-email-edge.vercel.app/api/preview https://react-email-edge.vercel.app/api/preview-edge

Apple Receipt (html)

https://react-email-edge.vercel.app/api/apple-receipt https://react-email-edge.vercel.app/api/apple-receipt-edge

bukinoshita commented 1 year ago

@mkreuzmayr Can we move this example in the examples folder on react-email?

mkreuzmayr commented 1 year ago

@bukinoshita For now, I am using the renderAsync.ts file directly instead of @react-email/render. Should I add it to the example folder as it is or add it as soon as renderAsync is merged?

bukinoshita commented 1 year ago

@bukinoshita For now, I am using the renderAsync.ts file directly instead of @react-email/render. Should I add it to the example folder as it is or add it as soon as renderAsync is merged?

Sorry for the delay. Yeah, let's move once this is merge and published.

ysm-dev commented 1 year ago

is it possible to use in Cloudflare Workers too?

mkreuzmayr commented 1 year ago

@ysm-dev Vercel's Edge Functions are built on top of Cloudflare Workers. So yeah, it should work.

ysm-dev commented 1 year ago

@mkreuzmayr I got this error during using react-email in cloudflare workers:

image

Do you know any solution?

rwieruch commented 1 year ago

@mkreuzmayr cannot thank you enough. Awesome work and awesome repository for reproduction :)

mkreuzmayr commented 11 months ago

@mkreuzmayr I got this error during using react-email in cloudflare workers: image

Do you know any solution?

I have never used React in Cloudflare Workers directly before, but I think the problem is that wrangler cannot handle the tsx syntax. Try building it with esbuild before.

rwieruch commented 9 months ago

Has the documentation this example somewhere? Because I am still using @mkreuzmayr renderAsync.ts file :)

shellscape commented 9 months ago

Doesn't look like the package was ever published, and there's no automation for publishing. I'm trying to get contributor access to help get the repo in shape.

mkreuzmayr commented 9 months ago

@rwieruch @shellscape The renderAsync function is already published. The example project is currently not in the react-email repo and documentation but you can update your renderAsync imports to point to @react-email/render and remove the renderAsync.ts you copied from my example.