electron / forge

:electron: A complete tool for building and publishing Electron applications
https://electronforge.io
MIT License
6.47k stars 513 forks source link

package command fails when using yarn workspaces with native dependency #3734

Open mtharrison opened 2 weeks ago

mtharrison commented 2 weeks ago

Pre-flight checklist

Electron Forge version

7.5.0

Electron version

v32.1.2

Operating system

MacOS 14.7

Last known working Electron Forge version

No response

Expected behavior

Electron-forge should dereference symlinks (or provide an option to) when copying the package.

Actual behavior

It does not dereference the symlinked dependencies leading to error:

✔ Copying files

An unhandled rejection has occurred inside Forge:
Error: ENOENT: no such file or directory, stat '/private/var/folders/bb/j1658g0d50gfcvgq3cm6cj1c0000gn/T/electron-packager/tmp-usVZSn/Electron.app/Contents/Resources/app/node_modules/asr'

Steps to reproduce

I'm using yarn (4.5.0) workspaces and I have packages

- packages
  - application (electron app)
  - asr (a native dependency)

asr is a dependency of application.

When I run yarn package it fails with the following error:

✔ Copying files

An unhandled rejection has occurred inside Forge:
Error: ENOENT: no such file or directory, stat '/private/var/folders/bb/j1658g0d50gfcvgq3cm6cj1c0000gn/T/electron-packager/tmp-usVZSn/Electron.app/Contents/Resources/app/node_modules/asr'

I see the dir it is stat'ing is a symlink:

 ls -al /private/var/folders/bb/j1658g0d50gfcvgq3cm6cj1c0000gn/T/electron-packager/tmp-usVZSn/Electron.app/Contents/Resources/app/node_modules/asr
lrwxr-xr-x@ 1 matt  staff  9  9 Oct 00:19 /private/var/folders/bb/j1658g0d50gfcvgq3cm6cj1c0000gn/T/electron-packager/tmp-usVZSn/Electron.app/Contents/Resources/app/node_modules/asr -> ../../asr

A workaround is running:

rm -rf ./node_modules/asr && cp -L -r ../asr ./node_modules/asr

If I run this and then rerun yarn package. The application will build correctly.

Is there any way to make electron-force understand it should dereference this symlink when copying the package?


I see a similar issue at https://github.com/electron/forge/issues/3624 with a suggested fix to the vite plugin. Would you be happy to take a PR for this?

Additional information

No response

mtharrison commented 2 weeks ago

I managed to trace the issue and I believe it is indeed related to the vite plugin. If I add the following to my package.json:

"config": {
    "forge": {
      "packagerConfig": {
        "extraResource": [
          "./node_modules/asr"
        ],
        "derefSymlinks": true
      }
    }
  }

It works now as expected. I can even delete the entire forge.config.ts and it still works, so I guess this snippet replaces entirely the forge config, meaning no vite pugin is used.

mtharrison commented 2 weeks ago

Ok I've got the vite plugin working now too. I had to do 2 things:

Here is my working forge.config.ts if it helps somebody else:

import type { ForgeConfig } from "@electron-forge/shared-types";
import { MakerSquirrel } from "@electron-forge/maker-squirrel";
import { MakerZIP } from "@electron-forge/maker-zip";
import { MakerDeb } from "@electron-forge/maker-deb";
import { MakerRpm } from "@electron-forge/maker-rpm";
import { VitePlugin } from "@electron-forge/plugin-vite";
import { FusesPlugin } from "@electron-forge/plugin-fuses";
import { FuseV1Options, FuseVersion } from "@electron/fuses";

const config: ForgeConfig = {
  packagerConfig: {
    asar: false,
    extraResource: ["./node_modules/asr"],
    derefSymlinks: true,
    ignore: (file) => {
      if (!file) {
        return false;
      }

      if (file.startsWith("/.vite")) {
        return false;
      }

      if (
        file === "/node_modules" ||
        file.startsWith("/node_modules/asr") ||
        file.startsWith("/node_modules/electron-squirrel-startup")
      ) {
        return false;
      }

      return true;
    },
  },
  makers: [
    new MakerSquirrel({}),
    new MakerZIP({}, ["darwin"]),
    new MakerRpm({}),
    new MakerDeb({}),
  ],
  plugins: [
    new VitePlugin({
      build: [
        {
          entry: "src/main.ts",
          config: "vite.main.config.ts",
          target: "main",
        },
        {
          entry: "src/preload.ts",
          config: "vite.preload.config.ts",
          target: "preload",
        },
      ],
      renderer: [
        {
          name: "main_window",
          config: "vite.renderer.config.ts",
        },
      ],
    }),
    new FusesPlugin({
      version: FuseVersion.V1,
      [FuseV1Options.RunAsNode]: false,
      [FuseV1Options.EnableCookieEncryption]: true,
      [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
      [FuseV1Options.EnableNodeCliInspectArguments]: false,
    }),
  ],
};

export default config;

Alternatively I can set ignore to ignore: [/^\/out\//g], however this increases my app size because it's including a lot of already bundled js.