react-email icon indicating copy to clipboard operation
react-email copied to clipboard

Cannot use @react-email/components with Cloudflare

Open colesanderson opened this issue 1 year ago • 10 comments

Describe the Bug

I keep getting error with Publish to Cloudflare Pages with Github Actions when using the @react-email/components.

Which package is affected (leave empty if unsure)

@react-email/components

Link to the code that reproduces this issue

no link

To Reproduce

Run cloudflare/pages-action@v1
npm warn exec The following package was not found and will be installed: [email protected]
npm warn deprecated [email protected]: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
npm warn deprecated [email protected]: Please use @jridgewell/sourcemap-codec instead
Delegating to locally-installed [email protected] over global [email protected]...
Run `npx wrangler pages publish ./build/client --project-name=web-starter-cloudflare --branch=main` to use the local version directly.
â–² [WARNING] `wrangler pages publish` is deprecated and will be removed in the next major version.
  Please use `wrangler pages deploy` instead, which accepts exactly the same arguments.
✨ Compiled Worker successfully
Uploading... (9/9)
✨ Success! Uploaded 0 files (9 already uploaded) (0.30 sec)
✨ Uploading _headers
✨ Uploading Functions bundle
✨ Uploading _routes.json
🌎 Deploying...
✘ [ERROR] Deployment failed!
  Failed to publish your Function. Got error: Error: Script startup exceeded CPU time limit.
🪵  Logs were written to "/home/runner/.config/.wrangler/logs/wrangler-2024-06-16_03-00-22_546.log"
npm notice
npm notice New minor version of npm available! [10](https://github.com/colesanderson/web-starter-cloudflare/actions/runs/9532835999/job/26275393016#step:6:11).7.0 -> 10.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.1
npm notice To update run: npm install -g [email protected]
npm notice
EXIT WHEN NOT EXPECTED
SHELLAC COMMAND FAILED!
Executing: npx wrangler@2 pages publish "./build/client" --project-name="web-starter-cloudflare" --branch="main" in /home/runner/work/web-starter-cloudflare/web-starter-cloudflare
STDOUT:
Delegating to locally-installed [email protected] over global [email protected]...
Run `npx wrangler pages publish ./build/client --project-name=web-starter-cloudflare --branch=main` to use the local version directly.
✨ Compiled Worker successfully
Uploading... (9/9)
✨ Success! Uploaded 0 files (9 already uploaded) (0.30 sec)
✨ Uploading _headers
✨ Uploading Functions bundle
✨ Uploading _routes.json
🌎 Deploying...
STDERR:
npm warn exec The following package was not found and will be installed: [email protected]
npm warn deprecated [email protected]: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
npm warn deprecated [email protected]: Please use @jridgewell/sourcemap-codec instead
â–² [WARNING] `wrangler pages publish` is deprecated and will be removed in the next major version.
  Please use `wrangler pages deploy` instead, which accepts exactly the same arguments.
✘ [ERROR] Deployment failed!
  Failed to publish your Function. Got error: Error: Script startup exceeded CPU time limit.
🪵  Logs were written to "/home/runner/.config/.wrangler/logs/wrangler-2024-06-[16](https://github.com/colesanderson/web-starter-cloudflare/actions/runs/9532835999/job/26275393016#step:6:17)_03-00-22_546.log"
npm notice
npm notice New minor version of npm available! 10.7.0 -> 10.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.1
npm notice To update run: npm install -g [email protected]
npm notice
node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "#<Object>".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

Code

import { json } from "@remix-run/cloudflare";
import { Resend } from "resend";
import { render } from "@react-email/render";
import { Button } from "@react-email/components";

export async function action(args: ActionFunctionArgs) {
  const { request, context } = args;
  const { env } = context.cloudflare;

  const resend = new Resend(env.RESEND_EMAIL);

  const Foo = () => (
    <Button href="https://example.com" style={{ color: "#61dafb" }}>
      Click me
    </Button>
  );

  const emailHtml = render(<Foo />);
  

  try {
    // Sending an email using the Resend API
    const { error } = await resend.emails.send({
      from: `Person <${defaultEmail}>`,
      reply_to: email,
      to: [defaultEmail],
      subject: "Form Submission",
      html: emailHtml,
      // render: <Foo /> // tried this too
    });

    if (error) {
      throw new Error("Failed to send email");
    }

    return json({ success: true, message: "Email sent successfully!" });
  } catch (error) {
    return json({ error: (error as Error).message }, 400);
  }
}

export default function Contact() {
  return <Contact />;
}

Expected Behavior

Expecting for deploy to work or output more helpful error?

What's your node version? (if relevant)

v20.10.0

colesanderson avatar Jun 16 '24 03:06 colesanderson

Please, make a proper minimal reproduction here. This might be caused by various things and to properly narrow down what is wrong, I wanted something that I could quickly use to reproduce your issue.

gabrielmfern avatar Jun 18 '24 17:06 gabrielmfern

Hey @gabrielmfern

  1. npm create cloudflare@latest my-remix-app -- --framework=remix
  2. Install resend, @react-email/render, @react-email/components
  3. Create a simple component using @react-email/components, can copy from https://demo.react.email/preview/notifications/vercel-invite-user?view=source
  4. Deploy to cloudflare
  5. Getting deploy error

colesanderson avatar Jun 18 '24 17:06 colesanderson

What version of render are you on?

gabrielmfern avatar Jun 18 '24 17:06 gabrielmfern

the newest version of render, I also tried with

resend.emails.send({
      react: <ContactEmail name={name} email={email} message={message} />,
    });

and

const emailHtml = ReactDOMServer.renderToString(<ContactEmail name={name} email={email} phone={phone} message={message} />);

    const { error } = await resend.emails.send({
      html: emailHtml,
    });

colesanderson avatar Jun 18 '24 18:06 colesanderson

Got a reproduction going, and it seems like installing the individual packages makes the error go away. Not sure exactly what might be causing this, if it's the exports that components does, or if it's because of Tailwind itself being so large at the moment.

Does not seem related to resend at all as well, as I could reproduce with just an action that renders the email template.

gabrielmfern avatar Jun 18 '24 18:06 gabrielmfern

This seems to be caused by Tailwind by trying to import the components individually until it errors on deploy. Pretty sure this is equivalent to #1101 and should be fixed by #1383.

gabrielmfern avatar Jun 19 '24 18:06 gabrielmfern

Any ETA for #1383 to complete? I'm also facing the same issue with Cloudflare pages, it is related to the Tailwind package too large. The size of the script already exceeded 3 MB and can't deploy it to Cloudflare pages.

sisheng1998 avatar Jul 10 '24 01:07 sisheng1998

Having the same problem here when deploying to Cloudflare Pages:

Error: Script startup exceeded CPU time limit.

I believe some work is being done in the global scope and I'm not sure what justifies that.

tavoyne avatar Jul 28 '24 16:07 tavoyne

For those looking for a fix, I'd suggest lazy importing every component.

const Body = lazy(async () => {
  return { default: (await import("@react-email/components")).Body };
});

This way, they won't bloat the global scope, resulting in faster startup, which makes sense whether this gets fixed or not.

tavoyne avatar Jul 29 '24 07:07 tavoyne

Importing components individually instead of via @react-email/components (including Tailwind) fixed the issue for me


import { Section } from '@react-email/section'
import { Body } from '@react-email/body'
import { Container } from '@react-email/container'
import { Img } from '@react-email/img'
import { Head } from '@react-email/head'
import { Preview } from '@react-email/preview'
import { Tailwind } from '@react-email/tailwind'
import { Html } from '@react-email/html'
import { Text } from '@react-email/text'
import { Link } from '@react-email/link'

nick avatar Aug 15 '24 21:08 nick

We just merged #1383 and released it under canary, @react-email/[email protected], should fix it

gabrielmfern avatar Oct 07 '24 15:10 gabrielmfern

@gabrielmfern the latest version again doesn't work on Cloudflare worker. any suggestion?

Image

vickyRathee avatar May 31 '25 14:05 vickyRathee

@vickyRathee start with making a reproduction and opening another issue, as the problem seems to be unrelated to this one

gabrielmfern avatar Jun 02 '25 11:06 gabrielmfern

@gabrielmfern please disregard, this is resolved by installing react and using await.

"react": "^19.1.0", "react-dom": "^19.1.0",

const html = await otpEmailHtml(authUser, otp);

In past versions react and await was not needed with hono and cf workers.

vickyRathee avatar Jun 02 '25 12:06 vickyRathee