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

bytecodePlugin doesn't work with electron 27.0.0 (MacOS universal) #315

Open
4 tasks done
theogravity opened this issue Oct 17, 2023 · 23 comments
Open
4 tasks done

Comments

@theogravity
Copy link

theogravity commented Oct 17, 2023

Describe the bug

Electron 27 just came out, and I seem to be having problems launching my built app when using the bytecode plugin

image

With electron 26, there are no issues.

My configuration looks like this:

// electron.vite.common.ts
import { externalizeDepsPlugin } from 'electron-vite';
import react from '@vitejs/plugin-react';

export const mainPlugins = [
  externalizeDepsPlugin({
    exclude: [
      '@nut-tree/nutjs',
      'node-mac-permissions',
    ],
  }),
];

export const mainRollupOptions = {
  external: ['node-mac-permissions', '@nut-tree/nutjs'],
};

export const preloadPlugins = [
  externalizeDepsPlugin({
    exclude: ['@monarch/electron-common'],
  }),
];

export const rendererPlugins = [react()];
// electron.vite.config.prod.ts
import { resolve } from 'path';
import { bytecodePlugin, defineConfig } from 'electron-vite';
import { mainPlugins, mainRollupOptions, preloadPlugins, rendererPlugins } from './electron.vite.common';

export default defineConfig({
  main: {
    plugins: mainPlugins.concat([bytecodePlugin()]),
    build: {
      rollupOptions: mainRollupOptions,
    },
  },
  preload: {
    plugins: preloadPlugins,
    build: {
      minify: true,
    },
  },
  renderer: {
    resolve: {
      alias: {
        '@renderer': resolve('src/renderer/src'),
      },
    },
    plugins: rendererPlugins,
    build: {
      minify: true,
    },
  },
});

Fuse configuration:

// ...
  await flipFuses(electronBinaryPath, {
    version: FuseVersion.V1,
    [FuseV1Options.EnableCookieEncryption]: true,
    resetAdHocDarwinSignature: electronPlatformName === 'darwin' && arch === builder.Arch.universal,
    [FuseV1Options.RunAsNode]: false,
    [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
    [FuseV1Options.EnableNodeCliInspectArguments]: false,
    [FuseV1Options.OnlyLoadAppFromAsar]: true,
    // Mac app crashes when enabled
    [FuseV1Options.LoadBrowserProcessSpecificV8Snapshot]: false,
    // electron-builder doesn't support: https://github.com/electron/fuses/issues/7
    [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: false,
  });
// ...

For notarization, we use notarytool.

package.json file

  "dependencies": {
    "@babel/plugin-transform-arrow-functions": "7.22.5",
    "@electron-toolkit/preload": "1.0.3",
    "@electron-toolkit/utils": "1.0.2",
    "@electron/fuses": "1.6.2",
    "electron-dl": "3.5.1",
    "electron-log": "5.0.0-rc.1",
    "electron-unhandled": "4.0.1",
    "electron-updater": "5.3.0"
  },
  "devDependencies": {
    "@electron-toolkit/tsconfig": "1.0.1",
    "@electron/notarize": "2.1.0",
    "@types/node": "18.17.14",
    "@types/react": "18.0.28",
    "@types/react-dom": "18.0.11",
    "@vitejs/plugin-react": "3.1.0",
    "autoprefixer": "10.4.16",
    "electron": "27.0.0",
    "electron-builder": "24.7.0",
    "electron-router-dom": "1.0.5",
    "electron-store": "8.1.0",
    "electron-vite": "1.0.28",
    "loglayer": "2.1.0",
    "macos-version": "6.0.0",
    "pkce-challenge": "3.1.0",
    "postcss": "8.4.30",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-router-dom": "6.8.2",
    "typescript": "5.2.2",
    "vite": "4.4.11"
  },
  "optionalDependencies": {
    "node-mac-permissions": "2.3.0"
  },
  "resolutions": {
    "postcss": "8.4.31",
    "semver": "7.5.4",
    "xml2js": "0.5.0"
  }

Electron-Vite Version

1.0.28

Electron Version

27.0.0

Vite Version

4.4.11

Validations

@theogravity
Copy link
Author

I see that you have committed ac47dac

Will you be publishing a new npm package soon?

Also, is this something that should be customizable by the user? It seems to be a potential maintenance issue when a new major electron version comes out. If a new version comes out, it'd be nice if I can manually specify the node and chrome version being used.

@theogravity
Copy link
Author

theogravity commented Oct 18, 2023

I wonder why it works no problem in 26 but not in 27 with the same config?

We haven't changed our build processes at all between 26 and 27.

We're also not manually specifying the electron version anywhere as your doc says could be an issue.

@alex8088
Copy link
Owner

I wonder why it works no problem in 26 but not in 27 with the same config?

We haven't changed our build processes at all between 26 and 27.

We're also not manually specifying the electron version anywhere as your doc says could be an issue.

Whether tested on the same operating system and the same architecture?

@alex8088
Copy link
Owner

I think you package your app with electron-builder's universal mode, universal is not supported. https://electron-vite.org/guide/source-code-protection.html#multi-platform-build

@theogravity
Copy link
Author

theogravity commented Oct 18, 2023

We've always been building Mac universal for the entire 25 and 26 electron without issues

Our CI build process hasn't changed at all

@alex8088
Copy link
Owner

We've always been building Mac universal for the entire 25 and 26 electron without issues

Our CI build process hasn't changed at all

This depends on the operating system architecture. If it is built with x64, you will have this error when installing on arm64, but there will be no problem when installing on x64. If it is built with arm64, there will be this error when installed on x64, but there will be no problem when installed on arm64. Bytecode is related to architecture. You can use the old version to test. I think CI is usually based on x64 architecture. You can install the old installation package in the m1/m2 macOS and this problem will be reproduced.

@theogravity
Copy link
Author

We've always been building Mac universal for the entire 25 and 26 electron without issues

Our CI build process hasn't changed at all

This depends on the operating system architecture. If it is built with x64, you will have this error when installing on arm64, but there will be no problem when installing on x64. If it is built with arm64, there will be this error when installed on x64, but there will be no problem when installed on arm64. Bytecode is related to architecture. You can use the old version to test. I think CI is usually based on x64 architecture. You can install the old installation package in the m1/m2 macOS and this problem will be reproduced.

My machine is an M2 and the 26 builds have no issues running. We've also tested with intel machines too.

@theogravity
Copy link
Author

theogravity commented Oct 18, 2023

You can also find our 26 build for mac universal on our download page.

We only build for mac universal.

https://www.switchboard.app/product/desktop-app

@alex8088
Copy link
Owner

Usually there will be problems with universal. You can try to package them into x64 and arm64 to see if the problem still exists.

@alex8088
Copy link
Owner

I don’t know if the universal installation package still selects x64 when installing m1/2.

@alex8088
Copy link
Owner

I learned from some developers that it is amazing that x64 bytecode can run in arm64, but it shouldn't be possible normally. This issue occurred after upgrading to version 27. this is a confusing issue.

@theogravity
Copy link
Author

theogravity commented Oct 23, 2023

I learned from some developers that it is amazing that x64 bytecode can run in arm64, but it shouldn't be possible normally. This issue occurred after upgrading to version 27. this is a confusing issue.

Is there a way for the plugin to generate bytecode for both arch and then select the correct one to use in a universal package?

@alex8088
Copy link
Owner

@theogravity Maybe it's possible. Check out: https://www.electron.build/configuration/mac.html

Note the mergeASARs and x64ArchFiles options, which may help us. Before using electron-builder packaging, we first specify different outDir to bundle code for the two architectures. Then use these two options to specify program code for different architectures. I haven't tried it, so I don't know if it's really possible.

@alex8088
Copy link
Owner

alex8088 commented Nov 8, 2023

@theogravity Have you found a way to handle universal packaging with bytecode? Can you share it?

@theogravity
Copy link
Author

I haven't tried anything yet. I'll probably not try it out until we actually need to upgrade to 27.

@lucasrabiec
Copy link

lucasrabiec commented Nov 9, 2023

I faced the same issue with x64 build for windows/linux on mac m1 (arm64 mac version works well on m1). I can't install the version on win x64 nor arm64. The issue occurs on Electron 27 and 28 (beta) but 26 works good.

@Kyun-J
Copy link

Kyun-J commented Dec 20, 2023

I had the same issue, but is resolved for now.
First, my app is not universal and I build x64 and arm64 separately.

The key to solving the problem was to run electron-vite build with a different ELECTRON_EXEC_PATH per arch as mentioned in the guide. I applied the following code to the beforePack of electron-builder and got the desired result. (This only works on arm-based Mac, x64 Mac will get an error when building arm64)

const { downloadArtifact } = require('@electron/get');
const { log } = require('builder-util');
const { spawnSync } = require('child_process');
const { Arch } = require('electron-builder');
const unzip = require('extract-zip');
const fs = require('fs');
const path = require('path');

const electronAppDirPath = path.resolve(__dirname, '.electron');

const getMacElectronAppPath = async (arch, version) => {
  log.info({ arch }, 'generate darwin electron according to arch');
  const zipPath = await downloadArtifact({
    version,
    platform: 'darwin',
    artifactName: 'electron',
    arch,
  });
  await unzip(zipPath, { dir: electronAppDirPath });
  return path.resolve(
    electronAppDirPath,
    'Electron.app/Contents/MacOS/Electron',
  );
};

const build = (option) => {
  return new Promise((resolve) => {
    const isAlpha = process.env.npm_lifecycle_event.includes('alpha');
    const buildCommand = isAlpha ? 'build:alpha' : 'build';

    log.info(`electron-vite ${buildCommand}`);
    const std = spawnSync('npm', ['run', buildCommand], option);
    if (std.stderr && std.stderr.length > 0) {
      log.error(std.stderr.toString());
    }
    resolve();
  });
};

exports.default = function (context) {
  return new Promise((resolve) => {
    const version = context.packager.info._framework.version;
    const platform = context.electronPlatformName;
    const arch = Arch[context.arch];

    if (platform !== 'darwin') {
      resolve();
      return;
    }

    getMacElectronAppPath(arch, version)
      .then((appPath) => {
        return build({
          env: {
            ...process.env,
            ELECTRON_EXEC_PATH: appPath,
          },
        });
      })
      .finally(() => {
        fs.rmSync(electronAppDirPath, { recursive: true, force: true });
        resolve();
      });
  });
};

However, the process is quite complicated. Hopefully there will be some improvements when using the bytecode plugin.

@rggagliardi-moveshelf
Copy link

We're replicating the same issue when packing an application from Linux x64 to Windows x64.
The installed application works with Electron 26.6.3, but not for Electron 27.x.x (or 28).
We get a similar CacheDataRejected exception
image

In particular we're using this Docker image electronuserland/builder:wine on our pipeline, building and packing the application for Windows. This is our electron.vite.config.js configuration:

import { defineConfig, bytecodePlugin } from 'electron-vite'
import { resolve } from 'path'

export default defineConfig({
  main: {
    plugins: [bytecodePlugin()],
    root: '.',
    build: {
      rollupOptions: {
        input: {
          index: resolve(__dirname, 'electron/main.ts')
        }
      }
    }
  },
  preload: {
    plugins: [bytecodePlugin()],
    build: {
      rollupOptions: {
        input: {
          index: resolve(__dirname, 'electron/preload.ts')
        }
      }
    }
  },
  renderer: {
    root: '.',
    build: {
      rollupOptions: {
        input: {
          index: resolve(__dirname, 'dist/polyb/index.html')
        }
      }
    }
  }
})

And our version details:

Angular 16
"electron": "^27.1.3",
"electron-builder": "^24.9.4",
"electron-vite": "^1.0.29",
Node 18.18.2

If I comment these lines plugins: [bytecodePlugin()], for main and preload, the installed application works, so we currently concluded the issue is about the Bytecode plugin with newer Electron versions.
Please let us know for any suggestion we could try

@lucasrabiec
Copy link

@alex8088 bytecode plugin issue still occurs with Electron 28 and electron-vite 2.0.0. Do you have any ideas on how to solve this problem?

@jashok5
Copy link

jashok5 commented Jan 27, 2024

在构建Mac universal app时,使用electron@28,我也遇到了同样的问题,我想知道这个问题是可以解决的吗

@alex8088 alex8088 changed the title bytecodePlugin doesn't work with electron 27.0.0 bytecodePlugin doesn't work with electron 27.0.0 (MacOS universal) Feb 22, 2024
@alex8088 alex8088 changed the title bytecodePlugin doesn't work with electron 27.0.0 (MacOS universal) bytecodePlugin doesn't work with electron 27.0.0 (MacOS universal) Feb 22, 2024
@murrayee
Copy link

Too.

@alon42
Copy link

alon42 commented Apr 3, 2024

The deep problem lies within the need to compile the bytecode, under Linux, using the Windows electron.exe file.
the bytecode plugin just calls the local electron, starts it with the flag "ELECTRON_RUN_AS_NODE=1" (which causes the electron to start as a simple node), and compiles the bytecode with it.

I tried a lot of workarounds, but Wine can't run electron.exe as a node properly under a Linux container, it is very hard to pass the input to the stdin of the wine-electron process.
and wine ALWAYS throws its own warnings and errors to the stdin.

After a day of struggling with it, I managed to make Wine run electron.exe inside the container and pass the stdin of the compiled file to the process, I quit when I realized that Wine had two problems:

first you need to make wine to manage to run node_modules/electron/dist/electron.exe without any errors.
so you'll have to extend electronuserland/builder:wine and install dependencies.

by adding:

FROM electronuserland/builder:wine

RUN apt update 
RUN apt upgrade -y

RUN apt install -y xorg xvfb xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic winbind
RUN wine reg add "HKCU\\Software\\Wine\\DllOverrides" /v winemenubuilder /d "" /f
RUN echo '#!/bin/bash\n\
export DISPLAY=:0.0\n\
Xvfb :0 -screen 0 1024x768x24 &\n\
exec "$@"' > /entrypoint.sh

# Make the entry point script executable
RUN chmod +x /entrypoint.sh

# Set the entry point to your script
ENTRYPOINT ["/entrypoint.sh"]

I managed to make wine node_modules/electron/dist/electron.exe to run inside a new docker image.

But:

  1. I didn't manage to make Wine run quietly, it always throws some errors to the stdout and it ends up inside the bytecode.
  2. Vite runs in parallel and starts multiple wine electron.exe, but wine is terrible in it, so even after managing to make a wine run electron.exe and passing the stdin to it, when you try to use it with electron-vite, it breaks due to the problem of running multiple wine programs in the same time.

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

No branches or pull requests

8 participants