electron / forge

:electron: A complete tool for building and publishing Electron applications

Home Page:https://electronforge.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

mangnus opened this issue · comments

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

This relates to an old issue: #869

But the fix only accounts for yarn workspaces...

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

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.

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.

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.

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!

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 @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 :).

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.

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.

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.

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)

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

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...
  }
}

Still seeing issues on npm 8.11.0 with workspaces

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

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.

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

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).