Skip to content
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

electron-forge does not work with npm workspaces (npm v7) #2306

Closed
3 tasks done
mangnus opened this issue Jun 4, 2021 · 21 comments · Fixed by #2446
Closed
3 tasks done

electron-forge does not work with npm workspaces (npm v7) #2306

mangnus opened this issue Jun 4, 2021 · 21 comments · Fixed by #2446
Labels

Comments

@mangnus
Copy link

mangnus commented Jun 4, 2021

Preflight Checklist

  • I have read the contribution documentation for this project.
  • I agree to follow the code of conduct that this project follows, as appropriate.
  • I have searched the issue tracker for a bug that matches the one I want to file, without success.

Issue Details

  • Electron Forge Version: 6.0.0-beta.57
  • Electron Version: 13.1.0
  • Operating System: macOS 11.4
  • Last Known Working Electron Forge version:: N/A

Expected Behavior

Running electron-forge start from project root (npm run start --workspace="packages/electron-app") or from electron workspace root (cd packages/electron-app && npm run start) should be able to locate the electron executable in the project root node_modules.

Actual Behavior

Running electron-forge start throws a PackageNotFoundError:

An unhandled rejection has occurred inside Forge:
PackageNotFoundError: Cannot find the package "electron". Perhaps you need to run "yarn install" in "<path-to-project-root>/packages/electron-app"?

To Reproduce

Minimal repro example: https://github.com/brightbrained/electron-forge-workspaces

Make sure to have npm v7 or above for workspaces support (npm install --global npm@latest)

git clone https://github.com/brightbrained/electron-forge-workspaces.git
cd electron-forge-workspaces
npm install
npm run start --workspace="packages/electron"

Additional Information

@mangnus mangnus added the bug label Jun 4, 2021
@mangnus
Copy link
Author

mangnus commented Jun 4, 2021

This relates to an old issue: #869

But the fix only accounts for yarn workspaces...

@jns-br
Copy link

jns-br commented Aug 12, 2021

I am running into exactly the same issue. Surprisingly electron-forge make works fine as long as you define
resolve: { modules: [path.resolve(__dirname, "../../node_modules"), "node_modules"], },
in webpack.main.config.js

@RandomEngy
Copy link

I was having this problem but fixed it by deleting a package-lock.json file in the electron subdirectory, allowing it to climb back to the root node_modules and find the electron package.

@jeanbmar
Copy link

jeanbmar commented Feb 8, 2022

If you read this and use NPM workspaces, you probably wonder why this issue is closed since it still doesn't work at all.
Electron Forge won't link properly the monorepo root node_modules directory during package and make operations, so you have to do it yourself.

@malept This issue should be reopened.

@jeanbmar
Copy link

Here's a working app using NPM workspaces: https://github.com/jeanbmar/black-moon-rewind/tree/r0.1-beta/packages/launcher
In order to get Forge working til the end, I had to write my own dependency resolver (np-bundle) and call it in Forge hooks because electron-packager won't resolve monorepo deps.

@robin-hartmann
Copy link

robin-hartmann commented Mar 21, 2022

Here's a working app using NPM workspaces: https://github.com/jeanbmar/black-moon-rewind/tree/r0.1-beta/packages/launcher In order to get Forge working til the end, I had to write my own dependency resolver (np-bundle) and call it in Forge hooks because electron-packager won't resolve monorepo deps.

I also had to set packagerConfig: { prune: false } in my forge config file, but then your bundler worked.

Thank you very much!

@robin-hartmann
Copy link

Based on @jeanbmar's resolver I now built my own one, which you can find in this gist. It is quite a bit shorter (and hopefully easier to understand), includes types and correctly skips all non-prod dependencies.

@jeanbmar
Copy link

jeanbmar commented Mar 21, 2022

Thank you @robin-hartmann. To give full credit to its author, my package is a modified version of npm/cli#4082. Your code looks great, you might want to share some feedback in the npm PR :).

@DrSkunk
Copy link

DrSkunk commented Apr 27, 2023

Based on @jeanbmar's resolver I now built my own one, which you can find in this gist. It is quite a bit shorter (and hopefully easier to understand), includes types and correctly skips all non-prod dependencies.

Thank you for the link. findRoot returns an object with rootDir, that's the only change I made so far that seems to make it work.

@itsdouges
Copy link

itsdouges commented May 2, 2023

Hi should we re-open this, or is there an issue on electron-packager for npm workspaces support? The current landscape seems quite dire unfortunately. I've taken the gist above and have added support for workspace packages also being copied over into node modules instead of being copied directly in the src folder. I can post it if folks would like. I could also publish it as a package if folks would be interested.

I've been on a rollercoaster trying to get electron forge and its dependencies working, moving away from pnpm + workspaces to npm + workspaces and then needing the above fix... really just wanted this all to work out of the box 🥲.

Pnpm support basically needs the same treatment as there is getting the core CLI working with pnpm, and then there is getting electron-packager working with it. Two separate problems that I was initially conflating to be the same. When I moved to npm I realized they weren't the same.

@jeanbmar
Copy link

jeanbmar commented May 2, 2023

Truth is neither NPM or Electron cares about packaging monorepo.

This pull request has been open for 1.5 year at NPM, and everyone involved just "ghosted" it.

Forge support for workspaces consists in letting NPM workspaces find Electron in the node_modules and completely ignores the fact that workspaces can't be packaged 🙃.

PNPM is probably the safe bet here.

@Eli-Black-Work
Copy link

Eli-Black-Work commented May 2, 2023

For what it's worth, we've been using electron-forge with Yarn 3 workspaces, and it works well 🙂 (You do need to set nodeLinker: node-modules, so that Yarn creates the node_modules folder instead of using Yarn PnP)

@itsdouges
Copy link

What do you do about electron packager and copying node modules over? Or you aren't using workspaces?

@Eli-Black-Work
Copy link

Our app is a React app. Our repo is structured like this:

app\
web\
src\

app\ is for electron, web\ is for compiling/running the app in a browser, and src\ is code that's shared between the two.

Our top-level package.json looks like this:

{
  "name": "example-root",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "web-run-dev": "yarn workspace example-web run run-dev",
    "web-build-prod": "yarn workspace example-web run build-prod",
    "app-run-dev": "yarn workspace example-app run run",
    "app-build-prod": "yarn workspace example-app run package"
  },
  "workspaces": [
    "app",
    "web",
    "src"
  ],
  "devDependencies": {
    "eslint": "8.29.0",
    "eslint-plugin-react": "7.31.11",
    "eslint-plugin-react-hooks": "4.6.0"
  },
  "packageManager": "yarn@3.3.0"
}

app\package.json looks like this:

{
  "name": "example-app",
  "productName": "Example",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "run": "electron-forge start",
    "package": "electron-forge package --platform win32 --arch ia32"
  },
  "main": ".webpack/main",
  "config": {
    "forge": {
      "packagerConfig": {
        "download": {
          "cacheRoot": "local-electron-cache"
        }
      },
      "makers": [],
      "plugins": [
        {
          "name": "@electron-forge/plugin-webpack",
          "config": {
            "devContentSecurityPolicy": "default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;",
            "mainConfig": "./webpack.main.config.js",
            "renderer": {
              "config": "./webpack.renderer.config.js",
              "entryPoints": [
                {
                  "html": "../src/index.ejs",
                  "js": "./renderer.js",
                  "name": "main_window",
                  "preload": {
                    "js": "./preload.js"
                  }
                }
              ]
            }
          }
        }
      ]
    }
  },
  "dependencies": {
    "electron-squirrel-startup": "1.0.0",
    "example-core": "*"
  },
  "devDependencies": {
    "@babel/core": "7.20.5",
    "@babel/preset-env": "7.20.2",
    "@babel/preset-react": "7.18.6",
    "@electron-forge/cli": "6.0.4",
    "@electron-forge/maker-squirrel": "6.0.4",
    "@electron-forge/plugin-webpack": "6.0.4",
    "babel-loader": "9.1.0",
    "copy-webpack-plugin": "11.0.0",
    "cross-env": "7.0.3",
    "css-loader": "6.7.2",
    "electron": "22.0.0",
    "style-loader": "3.3.1",
    "svg-sprite-loader": "6.0.11",
    "svgo": "3.0.2",
    "svgo-loader": "3.0.3",
    "webpack": "5.75.0",
    "webpack-cli": "5.0.1",
    "webpack-dev-server": "4.11.1"
  }
}

src\package.json looks like this:

{
  "name": "example-core",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "core-js": "3.26.1",
    "prop-types": "15.8.1",
    "regenerator-runtime": "0.13.11",
    ...etc...
  }
}

@itsdouges itsdouges mentioned this issue May 3, 2023
3 tasks
@stephenhandley
Copy link

Still seeing issues on npm 8.11.0 with workspaces

@Adrien5902
Copy link

I'm a bit late but i have found a solution you can use npm link electron inside your electron app package directory and it'll install electron locally in this package

@leoselig
Copy link

electron-forge DOES support npm workspaces, judging by its code (their is upwards traversal to monorepo root).

In my case, I had a faulty package-lock.json in my packages/sub-package causing electron-forge to assume that's the root. npm workspaces should only ever have a top-level package-lock.json so this was an error on my end and happened when bootstrapping the project via boilerplate repos.

@minikinl
Copy link

You should delete lock files in your packages according to source code:

the folder exist a lock file will be treated as the electron module root.

image

1j01 added a commit to 1j01/tracky-mouse that referenced this issue Apr 18, 2024
Electron Forge doesn't work with npm workspaces.
See: #53
And: electron/forge#2306
And: npm/cli#7029
And: npm/rfcs#287

This gets the app working when packaged.
@yagudaev
Copy link

yagudaev commented May 7, 2024

I also had this happen to me using yarn workspaces.

The solution was to delete the yarn.lock from the directory where you have electron installed. In my case it was rm desktop/yarn.lock (as suggested above).

@xiduzo
Copy link

xiduzo commented Jul 2, 2024

For me, the issue was resolved when using the webpack-typescript template instead of the vite-typescript template

@xiduzo
Copy link

xiduzo commented Jul 26, 2024

Here's a working app using NPM workspaces: https://github.com/jeanbmar/black-moon-rewind/tree/r0.1-beta/packages/launcher In order to get Forge working til the end, I had to write my own dependency resolver (np-bundle) and call it in Forge hooks because electron-packager won't resolve monorepo deps.

I come back to my previous comment, webpack-typescript setup was not much better. This solution worked for a while until I got the following error

An unhandled rejection has occurred inside Forge:
RangeError: Maximum call stack size exceeded
at ...path-to-workspace/apps/electron-app/bundler.js:52:14
    at Array.flatMap (<anonymous>)
    at collectProdDeps (...path-to-workspace/apps/electron-app/bundler.js:52:6)
    at ...path-to-workspace/apps/electron-app/bundler.js:52:40
    at Array.flatMap (<anonymous>)
    at collectProdDeps (...path-to-workspace/apps/electron-app/bundler.js:52:6)
    at ...path-to-workspace/apps/electron-app/bundler.js:52:40
    at Array.flatMap (<anonymous>)
    at collectProdDeps (...path-to-workspace/apps/electron-app/bundler.js:52:6)
    at ...path-to-workspace/apps/electron-app/bundler.js:52:40
    at Array.flatMap (<anonymous>)
    at collectProdDeps (...path-to-workspace/apps/electron-app/bundler.js:52:6)
    at ...path-to-workspace/apps/electron-app/bundler.js:52:40
    at Array.flatMap (<anonymous>)
    at collectProdDeps (...path-to-workspace/apps/electron-app/bundler.js:52:6)
    at ...path-to-workspace/apps/electron-app/bundler.js:52:40

I solved this by updating the collectProdDeps to

/** @type {(node: Node) => Node[]} */
const collectProdDeps = (node) => {
  const stack = [node];
  const result = new Set();  // Using a set to avoid duplicates and track visited nodes

  while (stack.length > 0) {
    const currentNode = stack.pop();
    const depEdges = [...currentNode.edgesOut.values()].filter((depEdge) => depEdge.type === "prod");

    for (const depEdge of depEdges) {
      const depNode = resolveLink(depEdge.to);

      if (!result.has(depNode)) {
        result.add(depNode);
        stack.push(depNode);
      }
    }
  }

  return Array.from(result);  // Convert the set to an array
};

Which seems to bundle the app properly.

Can't wait for electron-forge to "just" support this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.