forge
forge copied to clipboard
package command fails when using yarn workspaces with native dependency
Pre-flight checklist
- [x] I have read the contribution documentation for this project.
- [x] I agree to follow the code of conduct that this project uses.
- [x] I have searched the issue tracker for a bug that matches the one I want to file, without success.
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
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.
Ok I've got the vite plugin working now too. I had to do 2 things:
- Ensure my native dependency gets copied to the app bundle as vite is not bundling it
- Disable the
OnlyLoadAppFromAsarFuse
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.
Hey @mtharrison, thanks so much for your work on this! If it's no trouble, we'd definitely accept a PR to make this experience better or outline it more clearly in the docs. If you don't have time to do that, we can take a look at doing this 🙇♀
Sure, happy to. I'll take a look soon 😄