forge icon indicating copy to clipboard operation
forge copied to clipboard

Unable to load preload script

Open mikesongming opened this issue 1 year ago • 38 comments

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

6.0.0-beta.65

Electron version

20.1.0

Operating system

macOS12.5.1

Last known working Electron Forge version

No response

Expected behavior

use contextBridge to expose API in src/preload.js

Actual behavior

chome console shows error: unable to load preload script

Screen Shot 2022-08-31 at 15 41 11

Steps to reproduce

check the code at https://github.com/mikesongming/electron-forge-demo.git

Additional information

No response

mikesongming avatar Aug 31 '22 08:08 mikesongming

What worked for me was setting nodeIntegration: true, for mainWindow.

  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
      nodeIntegration: true,
    },
  });

MrRobz avatar Aug 31 '22 12:08 MrRobz

by setting nodeIntegration: true, context isolation is compromised. why nodeIntegration: false not supported?

There is an example of secure electron at: https://www.sitepoint.com/electron-forge-react-build-secure-desktop-app/

mikesongming avatar Aug 31 '22 13:08 mikesongming

Electron 20 is enable sandbox by default, I have to remove all npm package that uses deps that not in the sandbox.

See https://www.electronjs.org/docs/latest/tutorial/sandbox#preload-scripts for what we can use.

linonetwo avatar Sep 05 '22 18:09 linonetwo

Electron 20 is enable sandbox by default, I have to remove all npm package that uses deps that not in the sandbox.

See https://www.electronjs.org/docs/latest/tutorial/sandbox#preload-scripts for what we can use.

it says renderer process modules are available, however, when I use contextBridge, I get the error above.

Downmoto avatar Sep 05 '22 19:09 Downmoto

__dirname is not available too, it is out of the white list.

My solution is using IPC to get most of the value and methods

https://github.com/tiddly-gittly/TidGi-Desktop/blob/22f79c13ed1a498bd8767eecfe571a4e8b5e187d/src/preload/common/services.ts#L28

https://github.com/tiddly-gittly/TidGi-Desktop/blob/22f79c13ed1a498bd8767eecfe571a4e8b5e187d/src/services/native/index.ts#L182-L196

And use https://github.com/linonetwo/electron-ipc-cat

linonetwo avatar Sep 06 '22 04:09 linonetwo

The following seems to work for me (in development mode). However, in a packaged application I am still having the same issue.

const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true
    },
});

manuanish avatar Sep 06 '22 10:09 manuanish

Hey! The maintainers are taking a look at this, but we're unable to reproduce this on MacOS12.5.1- this is what we are seeing:

image

can you double check that the demo leads us to the correct error message? 🥂

georgexu99 avatar Sep 07 '22 21:09 georgexu99

https://github.com/electron/electron/blob/main/docs/breaking-changes.md#default-changed-renderers-without-nodeintegration-true-are-sandboxed-by-default

I suspect this error, as individuals above have mentioned stems from the electron 20 sandbox change. This means that you are unable to use __dirname in the renderer preload by default. For a quick fix, you can set sandbox: false in your browserWindow, but keep in mind that this goes against security best practices

georgexu99 avatar Sep 07 '22 22:09 georgexu99

Seems to me I am not getting the error on Ubuntu 22.04

image

Weird... Could be a windows bug?

manuanish avatar Sep 11 '22 06:09 manuanish

contextIsolation: true, // must be set to true when contextBridge is enabled nodeIntegrationInWorker: true, // must be set to true when contextBridge is enabled preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, // preload script enable contextBridge

----- I did this and it works using

handyzhang avatar Sep 13 '22 08:09 handyzhang

looks like preload is loaded before it's done build, when i save package.json everything works normally.

without contextIsolation & nodeIntegrationInWorker enabled

@georgexu99

DELEPaps avatar Sep 13 '22 12:09 DELEPaps

I was able to reproduce this with the release build of v6.0.0 on MacOS 12.5 by trying to use a Web Worker.

Specifically by using worker-loader and adding this rule to the webpack.renderer.config.js

rules.push({
  test: /\.worker\.js$/,
  use: { loader: "worker-loader", options: { inline: "fallback" } },
});

Here is my preload script:

import Worker from "./test.worker";

const worker = new Worker();

worker.postMessage("Hello from worker!");

And here is my worker code:

onmessage = function (e) {
  console.log(e.data);
};

Setting sandbox to false prevents the issue but it would be good to avoid that.

mitchemmc avatar Nov 06 '22 03:11 mitchemmc

@mitchemmc Are you able to reproduce this issue without worker-loader? I see that package was deprecated in Webpack 5, which is the major version used in Forge 6.

https://webpack.js.org/guides/web-workers/

erickzhao avatar Nov 07 '22 22:11 erickzhao

@mitchemmc Are you able to reproduce this issue without worker-loader? I see that package was deprecated in Webpack 5, which is the major version used in Forge 6.

https://webpack.js.org/guides/web-workers/

Unfortunately the new method doesn't work with Electron Forge.

Specifically when using:

new Worker(new URL('./worker.js', import.meta.url));

It will give a 404 error

Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:3000/Users/mitch/Documents/Tests/forge-preload-webpack/.webpack/renderer/main_window/native_modules/worker.js

mitchemmc avatar Nov 07 '22 23:11 mitchemmc

@erickzhao

Ok I was able to get the new worker method to work. If you create a new url with the import.meta.url then webpack will pick up the worker.js file and include it in the bundle. Then if I hard code the worker path into the worker creation like this:

new URL("./worker.js", import.meta.url);
const worker = new Worker("/main_window/native_modules/worker.js");

This will make use of the local dev server so we can test it (although this method won't work in a production build).

Unfortunately after this I get the same issue as a worker-loader plugin.

It works with sandbox set to false but I still get a ReferenceError: __dirname is not defined error with sandbox enabled.

mitchemmc avatar Nov 07 '22 23:11 mitchemmc

The native_modules folder path is suspect.

It seems like the @vercel/webpack-asset-relocator-loader loader is causing this problem. Commenting it out makes the minimal example from the webpack docs work both in dev mode and packaged mode.

See repro: https://github.com/erickzhao/ericktron-forge/commit/ea27cf9018f7163eb76c4355bb0a9113f59a7f96

I think I'll open a separate issue for this!

erickzhao avatar Nov 07 '22 23:11 erickzhao

Interesting, it seems that removing the webpack-asset-relocator-loader I was able to get workers to work in the renderer but it still seems to run in to issues if I try and create the worker in a preload script.

mitchemmc avatar Nov 08 '22 00:11 mitchemmc

Workers don't work in preload scripts as they run before a document context is initialized (this is an electron limitation). If we register the worker in the preload inside an window.onload event handler it will also work.

MarshallOfSound avatar Nov 08 '22 00:11 MarshallOfSound

@MarshallOfSound hmm, I've been using workers in preload scripts for a while now and haven't had many issues 🤔

The main issue I'm seeing is with sandboxing. Having it enabled seems to run in to these __dirname issues.

Here's a repro that incorporates what @erickzhao found with the webpack-asset-relocator-loader plugin.

https://github.com/mitchemmc/forge-worker-sandbox

If I disable sandboxing then it seems to work.

mitchemmc avatar Nov 08 '22 00:11 mitchemmc

I suspect this error, as individuals above have mentioned stems from the electron 20 sandbox change. This means that you are unable to use __dirname in the renderer preload by default. For a quick fix, you can set sandbox: false in your browserWindow, but keep in mind that this goes against security best practices

Converting to a relative URL for my preload script works!

GreenBattery avatar Nov 08 '22 19:11 GreenBattery