From 174f9cd7fb3cfe463f762cfb6cc743bb0301d4c6 Mon Sep 17 00:00:00 2001 From: Gabriel Miranda Date: Fri, 5 Sep 2025 10:48:59 -0300 Subject: [PATCH] fix: builds errors with esbuild and react-dom@18 (#2436) --- .changeset/shy-moons-smell.md | 5 +++++ packages/render/src/edge/import-react-dom.tsx | 17 ++++++++++------- packages/render/src/edge/render.tsx | 6 +++--- 3 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 .changeset/shy-moons-smell.md diff --git a/.changeset/shy-moons-smell.md b/.changeset/shy-moons-smell.md new file mode 100644 index 000000000..b4a293da7 --- /dev/null +++ b/.changeset/shy-moons-smell.md @@ -0,0 +1,5 @@ +--- +"@react-email/render": patch +--- + +fix builds failing with esbuild and react-dom@18 diff --git a/packages/render/src/edge/import-react-dom.tsx b/packages/render/src/edge/import-react-dom.tsx index 846f46a2f..ee9a34a89 100644 --- a/packages/render/src/edge/import-react-dom.tsx +++ b/packages/render/src/edge/import-react-dom.tsx @@ -1,8 +1,11 @@ -export const importReactDOM = async () => { - try { - return await import('react-dom/server.edge'); - } catch (_exception) { - // This ensures that we still have compatibiltity with React 18, which doesn't have the `edge` conditional export. - return await import('react-dom/server'); - } +export const importReactDom = () => { + // We don't use async here because tsup converts it to a generator syntax + // that esbuild doesn't understand as dealing with the import failing during + // bundling: https://github.com/evanw/esbuild/issues/3216#issuecomment-1628913722 + return import('react-dom/server.edge').catch( + () => + // This ensures that we still have compatibility with React 18, + // which doesn't have the `.edge` export. + import('react-dom/server'), + ); }; diff --git a/packages/render/src/edge/render.tsx b/packages/render/src/edge/render.tsx index 84fdb8300..7102a6c44 100644 --- a/packages/render/src/edge/render.tsx +++ b/packages/render/src/edge/render.tsx @@ -3,15 +3,15 @@ import { pretty } from '../node'; import type { Options } from '../shared/options'; import { readStream } from '../shared/read-stream.browser'; import { toPlainText } from '../shared/utils/to-plain-text'; -import { importReactDOM } from './import-react-dom'; +import { importReactDom } from './import-react-dom'; export const render = async ( element: React.ReactElement, options?: Options, ) => { const suspendedElement = {element}; - const reactDOMServer = await importReactDOM().then( - // This is beacuse react-dom/server is CJS + const reactDOMServer = await importReactDom().then( + // This is because react-dom/server is CJS (m) => m.default, );