resend / react-email

💌 Build and send emails using React

Home Page:https://react.email

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

  1. Create a pnpm workspace
  2. 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.

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.

commented

Can we configure the client to work with pnpm by default?

@seawatts @jeanhdev I ended up forking the project to get around this. you can find the fork on my GitHub profile.

Running into this now as well

@bukinoshita If I understand correctly, the current model of the preview server is:

  1. 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)
  2. Install dependencies inside the newly created .react-email project
  3. Instantiate a watcher to sync emails into the .react-email project
  4. 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

commented

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!

commented

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:

  1. 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)
  2. Install dependencies inside the newly created .react-email project
  3. Instantiate a watcher to sync emails into the .react-email project
  4. 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

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:

  1. Remove .react-email and node_modules from your emails project if it is already there.
  2. Once you have the email project setup npx create-email@latest with no .react-email and node_modules or the wrong lock file. Run pnpm i from the root.
  3. Now add .react-email project to the pnpm-workspace.yml
  4. Run pnpm i again
  5. 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"
  }
}