-
Notifications
You must be signed in to change notification settings - Fork 654
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
renderToReadableStream not found in react-dom/server #868
Comments
Same issue here. Problem most likely is, that this is only supported on environments which support WebStreams. This makes it impossible to run on some backends. |
Maybe this helps someone: I needed a quick fix since my webpack kept crashing due to this function not being available in my NodeJS environment. I used /* webpack.config.js */
const path = require("path");
const { NormalModuleReplacementPlugin } = require("webpack");
module.exports = {
// ...
plugins: [
new NormalModuleReplacementPlugin(
/email\/render/,
path.resolve(__dirname, "./src/renderEmailFix.js"),
),
],
// ...
}; // @ts-nocheck
const { renderToStaticMarkup } = require("react-dom/server");
module.exports.render = (component) => {
const doctype =
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
const markup = renderToStaticMarkup(component);
return `${doctype}${markup}`;
}; |
Here's what the fix for this looks like shellscape/jsx-email@2eeebfc |
For me this issue pops up with the latest Next.js release v13.5.6, which bumped the version of React it uses |
I've been using this happily with Next.js 13.5.6 but it fails immediately on upgrade to Next.js 14.0.0. |
Thank you so much @shellscape! Here is a patch file that implements this for
|
Can confirm this completely breaks on Next 14.0.0 |
@subvertallchris no prob. fwiw we've completely moved away from using react for rendering, which makes it fully compatible with edge and all fe frameworks. using react for rendering was a big footgun |
Confirming that react email worked fine until upgrading to next 14. |
Following, exited to get rid of experimental in next.config.js I updated to 14 and now get ./node_modules/@react-email/render/dist/index.mjs |
Yup this breaks on upgrade to Next 14 🙃 |
Yes indeed, very much busted on Next 14. |
So now there are no patch/fix solution for react-email with Next 14 ? |
My experience with https://github.com/shellscape/jsx-email has been good so far. It's easier to set up the preview server and bugs get fixed quickly if you offer a reproduction. |
Also unable to get working with NextJS 14 |
Is there any progress on this that would allow us to monitor its status? |
If anyone is looking for a temporary NextJS 14 fix (using @Moicky's solution) in next.config.js add these imports:
& add this webpack configuration somewhere in the file:
Finally, create a new file
|
The patch file I posted yesterday is also working fine for me.
…On Fri, Oct 27, 2023 at 7:43 AM themendelson ***@***.***> wrote:
If anyone is looking for a temporary NextJS 14 fix -
in next.config.js add these imports:
const path = require("path");
const {
NormalModuleReplacementPlugin
} = require("webpack");
& add this webpack configuration somewhere in the file:
webpack: (
config, {
buildId,
dev,
isServer,
defaultLoaders,
nextRuntime,
webpack
}
) => {
config.plugins = config.plugins || []
config.plugins.push(new NormalModuleReplacementPlugin(
/email\/render/,
path.resolve(__dirname, "./renderEmailFix.js"),
))
// Important: return the modified config
return config
}
Finally, create a new file renderEmailFix.js in the root folder with this
code:
// @ts-nocheck
const {
renderToStaticMarkup
} = require("react-dom/server");
module.exports.render = (component) => {
const doctype =
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
const markup = renderToStaticMarkup(component);
return `${doctype}${markup}`;
};
—
Reply to this email directly, view it on GitHub
<#868 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA7IJ53PGXWRVS2V5WLVRATYBOM4RAVCNFSM6AAAAAA2Z5JI52VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTOOBSG43TCOJRG4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
We're currently working on a fix for that. Will keep you all posted. |
The new release doesn't work because in https://www.npmjs.com/package/@react-email/components?activeTab=code |
If you're facing difficulties after upgrading to Next.js 14, you may find this workaround useful. I created a new utility function called // @utils/renderEmailHtml.ts
import type {ReactElement} from 'react';
import type {ReactDOMServerReadableStream} from 'react-dom/server';
async function readStream(readableStream: ReactDOMServerReadableStream) {
const reader = readableStream.getReader();
const chunks: AllowSharedBufferSource[] = [];
while (true) {
const {value, done} = await reader.read();
if (done) {
break;
}
chunks.push(value);
}
return chunks.map((chunk) => new TextDecoder('utf-8').decode(chunk)).join('');
}
export async function renderEmailHtml(component: ReactElement) {
// @see https://github.com/vercel/next.js/issues/43810#issuecomment-1462075524
// Dynamically import ReactDOMServer to circumvent:
// "Unable to import react-dom/server in a server component"
const reactDOMServer = (await import('react-dom/server')).default;
// Note: only available in platforms that support WebStreams
// https://react.dev/reference/react-dom/server/renderToString#alternatives
const renderToStream =
reactDOMServer.renderToReadableStream ||
reactDOMServer.renderToPipeableStream;
const doctype =
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
const readableStream = await renderToStream(component);
const html = await readStream(readableStream);
html
// Remove leading doctype becuase we add it manually
.replace(/^<!DOCTYPE html>/, '')
// Remove empty comments to match the output of renderToStaticMarkup
.replace(/<!-- -->/g, '');
return `${doctype}${html}`;
}
Usage in, for example, GET // @app/api/email/welcome/route.ts
import Welcome from '@emails/Welcome';
import {renderEmailHtml} from '@utils/renderEmailHtml';
export const runtime = 'edge';
export async function GET() {
// ...
const emailHtml = await renderEmailHtml(
Welcome({name}),
);
// ...
} That solution worked for me. |
I'm wondering what's your setup, if one can confirm how are you using? I'm testing this way in next.js 14 import { render } from '@react-email/render';
import { MyEmail } from '../../../emails/my-email';
import { NextResponse } from 'next/server';
export const runtime = 'edge'
export const GET = async () => {
const html = await render(MyEmail());
return NextResponse.json({ html }, { status: 200 })
} |
@bukinoshita I think using render package in any node/edge environment would cause this. (personally using nodejs). I think problem also occurs when just installing render package with pnpm. |
I'm using the plain fetch as a work around, here is an example from the official doc: import { NextResponse } from 'next/server';
export const runtime = 'edge';
export const dynamic = 'force-dynamic';
const RESEND_API_KEY = 're_123456789';
export async function POST() {
const { renderToStaticMarkup } = await import('react-dom/server');
const res = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${RESEND_API_KEY}`,
},
body: JSON.stringify({
from: 'Acme <onboarding@resend.dev>',
to: ['delivered@resend.dev'],
subject: 'hello world',
html: renderToStaticMarkup(<Email />),
}),
});
if (res.ok) {
const data = await res.json();
return NextResponse.json(data);
}
} |
Can you try using the canary version of render to see if this is still happening? {
...,
"@react-email/render": "0.0.9-canary.0",
} |
We just released a new canary version here's an example on Next.js 14 app router edge import { NextResponse } from 'next/server';
import { EmailTemplate } from '../../../components/email-template';
import { renderAsync } from '@react-email/render';
export const runtime = 'edge';
export async function GET() {
try {
const html = await renderAsync(
EmailTemplate({ firstName: 'John' }) as React.ReactElement
);
return NextResponse.json({ html });
} catch (error) {
return NextResponse.json({ error });
}
} |
Working for me...appreciate the fast work |
+1 for migrating to |
+1 for jsx-email. Worked on first try. No additional installations, various errors and long debugging. Thanks to those that recommended it. I updated to react-email 9 and resend 2 and still had multiple errors. Decided to give jsx-email a try from all the comments here. |
Just in case the fix from PR #1009 does not work for someone using Next.js 14: I figured out that the last version of @react-email/render is not installing automatically. You need to go to package.json under the .email folder that is automatically created and upgrade @react-email/render to 0.0.9. Also I upgraded postcss to 8.4.21 (was unmet dependency for the version that is automatically installed, 8.4.19) I also removed the appDir experimental function from next.config.js (again, under the .email folder) - as according to Next is no longer valid. With this changes now works perfectly. |
As @bukinoshita mentioned, the fix is in We'll just need to upgrade your local
|
Thank you - your solution works for me |
None of the options above worked for me. I might have found a solution though: installing components separately, rather than using
Everything works great and builds with no errors, even with the latest version of |
Unfortunately, it doesn't work for me... neither does the above one... |
I struggled with the initial guidance as well, I did a lot of tinkering, and this is what I currently have that got it working. Unfortunately, I cannot explain why it works now.
Resend you mail provider? Minor changes are required here around chaining methods. Resend.emails.send() instead of Resend.sendEmail() Also change react: to html: now that you are using renderAsync to generate the HTML of the email.` |
I also moved to jsx-email. Way better and is not breaking. Migration took 10 minutes. |
Thanks! This didn't work either... :-( |
updating @react-email/render from 0.0.7 to "@react-email/render": "^0.0.9", (with --force) worked for me, just to mention @blakebullis comment about the break in pY pX properties in buttons, it also happened to me. |
renderIf you're still having issues with Eg: import { renderAsync } from '@react-email/render'
const html = async renderAsync(EmailTemplate({ firstName: 'John' })) componentsIf you're still having issues with Eg: import { renderAsync } from '@react-email/components'
const html = async renderAsync(EmailTemplate({ firstName: 'John' })) resendIf you're still having issues with Eg: const { data, error } = await resend.emails.send({
from: 'team@example.com',
to: 'delivered@resend.dev',
subject: 'Hello!',
react: EmailTemplate({ firstName: 'John' })
}) Still having issues after upgrading
|
Okay, the solution was simpler than expected. Even though I updated package.json with the appropriate version, the package-lock.json contained the older versions, and the app somehow picked those (something something about the node module resolution algorithm). To fix this, I added the line " Many thanks to @lxunos for the fix/lesson. 🙏 |
This actually worked, thanks! Delete package-lock and node_modules, npm i, and it's working. |
Hey Guys, Those who use the Resend library, update to V2.0.0, it works in Next14. https://www.npmjs.com/package/resend |
No luck with any of the above packages. What magic are you all using? 😂 |
Ops, you're in for a rough one then. 👀 |
Is there a reproducible code? |
@catalinpit I was able to resolve the issue as well. Thank you.
|
I tried the solutions above but none of it worked, I just manage to solve downgrading my packges and changing some setting on the next.config.js My {
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"email": "email dev --dir src/emails"
},
"dependencies": {
"@react-email/components": "0.0.6",
"next": "^13.4.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-email": "1.9.3",
"react-is": "^18.2.0",
},
"devDependencies": {
"@types/node": "^17.0.45",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"typescript": "^5"
}
}
And my /** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: {
appDir: true,
},
}
export default nextConfig After changing these files, deleting |
What i do to resolve the issue
|
Installing |
I resolve the issue using in next.config.js
|
It worked for me "@react-email/components": "^0.0.11",
"@react-email/render": "0.0.9-canary.2", my nextjs version: "next": "14.0.4", |
It works for me, Thank you. |
Confirmed on |
Describe the Bug
We are testing out react-email for use in our project, but getting this error when trying to deploying a test template:
Template code:
Package.json versions
Which package is affected (leave empty if unsure)
@react-email/components
Link to the code that reproduces this issue
n/a
To Reproduce
Deploy with the listed package versions -
We're using serverless: '"start": "serverless offline --httpPort 4051 --stage local --host 0.0.0.0"'
Expected Behavior
The code should compile cleanly without this import error
What's your node version? (if relevant)
18.13.0
The text was updated successfully, but these errors were encountered: