email command fails within pnpm workspace
KrisBraun opened this issue · comments
Describe the Bug
Following the manual setup inside a pnpm monorepo with a pnpm-workspace.yaml
in the root, the email command fails like this:
✔ Emails preview generated
⠋ Installing dependencies...
Scope: all 13 workspace projects
✔ Dependencies installed
> react-email-client@0.0.14 dev /Users/.../libs/email/.react-email
> next dev "--" "-p" "8790"
sh: next: command not found
ELIFECYCLE Command failed.
WARN Local package.json exists, but node_modules missing, did you mean to install?
Turns out a script was running a pnpm install
command, but since it's in the workspace, it simply installed the other packages, but skipped the new one since it doesn't match a pattern.
I solved this by adding [package-path]/.react-email
in pnpm-workspace.yaml
. Not sure the best general solution. Posting here mainly to help anyone else hitting the same issue.
Which package is affected (leave empty if unsure)
react-email
Link to the code that reproduces this issue
https://react.email/docs/getting-started/manual-setup
To Reproduce
- Create a pnpm workspace
- Follow https://react.email/docs/getting-started/manual-setup within a package
Expected Behavior
The email
command would succeed, or at least provide a clearer error.
What's your node version? (if relevant)
No response
Also just ran into this
I am also having this issue when using it though pnpm workspaces. For now the only work around I use is to go into the .react-email folder and do a yarn install
. Then the email dev
command works pretty well after this.
The issue is here: https://github.com/resendlabs/react-email/blob/490e0356685c1a6406c89620687725d0b98ad53b/packages/react-email/source/utils/sync-package.ts#L6 and doesn't seem to take into account pnpm or pnpm workspaces.
Using a node_modules/dependency script (https://github.com/resendlabs/react-email/blob/490e0356685c1a6406c89620687725d0b98ad53b/packages/react-email/source/utils/start-server-command.ts#L15 and https://github.com/resendlabs/react-email/blob/490e0356685c1a6406c89620687725d0b98ad53b/client/package.json#L7) is a really weird way to spin up a process. The concept of package binaries exists so authors don't have to do those kinds of shenanigans.
Alright fast followup: If you run npm install
within the .react-email
directory (even though we're using pnpm), it'll install packages into node_modules
and the dev server will run.
I maintain that this is a pretty bad way to ship a dev server, but that's a workaround that requires some manual steps. If you're using a build tool like moon, this step can probably be automated.
Confirmed, @shellscape solution resolves it. Would still like to see this fixed as well though.
Can we configure the client to work with pnpm
by default?
+1
Running into this now as well
+1
@bukinoshita If I understand correctly, the current model of the preview server is:
- Download a tarball archive that includes a client directory which is in itself a node project, and extract that directory out of the tarball into a folder (.react-email)
- Install dependencies inside the newly created .react-email project
- Instantiate a watcher to sync emails into the .react-email project
- Run the nextjs dev server
This seems overly complex. If someone is using the react-email
package then they will, with absolute certainty, need to install the dependencies inside client
at some point in life. Why are those dependencies only defined there, rather than have them exist as dependencies of react-email
itself?
Which brings me to my next question - Why is client
downloaded extracted and ran as a separate project? The next server could be created from within the cli tool, which would fix this issue
I'd be glad to work on a PR for the aforementioned change if it's relevant
Any progress on this?
@JasonMan34 Could you please provide more details on your solution? How would you use next cli to fix this issue? I could fork and use your solution until the fix has been released. Thank you!
The Dev X is bad, I get a tons of errors.
Why can't we use pnpm as default ?
Fixed it on my end by
-> removing .react-email
build & node_modules
-> installing globally yarn and next with pnpm i -g next && pnpm i -g yarn
-> running pnpm i
-> running pnpm run dev
with no errors
I'm using this patch as a workaround to use this package in a pnpm
project. You may use it with the patch feature in pnpm
.
# patches/react-email@1.9.5.patch
diff --git a/dist/source/utils/install-dependencies.js b/dist/source/utils/install-dependencies.js
index 24f4a82f14037a4e341775fe4f273016adf8ac2e..155ff41d5d3bfb3d185f774703bcd1033096580d 100644
--- a/dist/source/utils/install-dependencies.js
+++ b/dist/source/utils/install-dependencies.js
@@ -11,6 +11,10 @@ const ora_1 = __importDefault(require("ora"));
const log_symbols_1 = __importDefault(require("log-symbols"));
const close_ora_on_sigint_1 = require("./close-ora-on-sigint");
const installDependencies = async (packageManager) => {
+ if(packageManager === 'pnpm'){
+ console.warn(`\n🚨🚨🚨🚨🚨🚨\nUsing \`npm\` instead of \`${packageManager}\` to install react-email preview app dependencies\nThis patch should be removed when react-email can support existing in a pnpm workspace.\nsee: https://github.com/resendlabs/react-email/issues/881\n🚨🚨🚨🚨🚨🚨\n`);
+ packageManager = 'npm';
+ }
const spinner = (0, ora_1.default)('Installing dependencies...\n').start();
(0, close_ora_on_sigint_1.closeOraOnSIGNIT)(spinner);
shelljs_1.default.cd(path_1.default.join(constants_1.REACT_EMAIL_ROOT));
pretty easy workaround is to add the .react-email folder to your pnpm-workspaces.yaml
packages:
- "packages/*"
- "apps/**"
- "apps/email/.react-email"
edit: to add more explanation, pnpm workspaces don't look for hidden directories that start with .
, which is why you need to manually add it in the pnpm-workspaces.yaml
file. there technically is no bug or issue here, it's just how pnpm works
pretty easy workaround is to add the .react-email folder to your
pnpm-workspaces.yaml
packages: - "packages/*" - "apps/**" - "apps/email/.react-email"
We experienced the same issue in our monorepo, this workaround worked for us.
@bukinoshita If I understand correctly, the current model of the preview server is:
- Download a tarball archive that includes a client directory which is in itself a node project, and extract that directory out of the tarball into a folder (.react-email)
- Install dependencies inside the newly created .react-email project
- Instantiate a watcher to sync emails into the .react-email project
- Run the nextjs dev server
This seems overly complex. If someone is using the
react-email
package then they will, with absolute certainty, need to install the dependencies insideclient
at some point in life. Why are those dependencies only defined there, rather than have them exist as dependencies ofreact-email
itself? Which brings me to my next question - Why isclient
downloaded extracted and ran as a separate project? The next server could be created from within the cli tool, which would fix this issueI'd be glad to work on a PR for the aforementioned change if it's relevant
100% agree, finally getting around to looking into react email. Sounded promising, but now I see this and I feel like it was made with little thought to how fragile this approach is.
This is not a good developer experience, I am fighting with the tool that's suppose to make our life easier for working with emails.
Workaround, step by step:
- Remove
.react-email
andnode_modules
from your emails project if it is already there. - Once you have the email project setup
npx create-email@latest
with no.react-email
andnode_modules
or the wrong lock file. Runpnpm i
from the root. - Now add
.react-email
project to thepnpm-workspace.yml
- Run
pnpm i
again - Now you can run it
pnpm --filter emails run dev
.
├── .react-email
├── node_modules
├── package.json
├── src
│ └── emails
│ ├── index.tsx
│ ├── notion-magic-link.tsx
│ ├── plaid-verify-identity.tsx
│ ├── stripe-welcome.tsx
│ └── vercel-invite-user.tsx
├── static
│ ├── notion-logo.png
│ ├── plaid-logo.png
│ ├── plaid.png
│ ├── stripe-logo.png
│ ├── vercel-arrow.png
│ ├── vercel-logo.png
│ ├── vercel-team.png
│ └── vercel-user.png
├── tree
└── tsconfig.json
4 directories, 16 files
Here's the structure of the emails package I am housing my setup within.
In the root of my mono repo I have
packages:
- "apps/*"
- "packages/emails/.react-email"
- "packages/*"
-
It would be nice if the default package manager could be selected via a cli arg. Instead of it defaulting to whatever it finds on the system first.
You might also need to add it to .eslintignore
Problem
If you clone the repo from scratch, since .react-email
is not in version control the package path won't exist. I tested cloning the repo from fresh and ran pnpm i
and then pnpm --filter emails run dev
and it worked fine.
{
"name": "@bob/emails",
"version": "0.0.1",
"scripts": {
"dev": "email dev -d ./src/emails/ -p 3003",
"export": "email export -d ./src/emails/"
},
"dependencies": {
"@react-email/components": "0.0.12",
"react-email": "1.10.0"
},
"devDependencies": {
"@types/node": "^20.6.0",
"typescript": "^5.1.6"
}
}