forge icon indicating copy to clipboard operation
forge copied to clipboard

Unable to load preload script

Open mikesongming opened this issue 2 years ago • 42 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
    },
});

not-manu avatar Sep 06 '22 10:09 not-manu

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?

not-manu avatar Sep 11 '22 06:09 not-manu

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

+1

I also am having this same issue now with Electron 20, using the Webpack plugin (https://www.electronforge.io/config/plugins/webpack). My local preload script combines with webpack to a new preload.js which uses __dirname. If I go outside webpack and add my own preload ONLY, then I get an error that I cannot import outside of modules (so I can't set up the IPC context bridge correctly).

I don't see a solution here besides enabling nodeIntegration / disabling sandbox (less secure), or simply downgrading electron :-/

aarowman avatar Dec 17 '22 00:12 aarowman

+1

I also am having this same issue now with Electron 20, using the Webpack plugin (https://www.electronforge.io/config/plugins/webpack). My local preload script combines with webpack to a new preload.js which uses __dirname. If I go outside webpack and add my own preload ONLY, then I get an error that I cannot import outside of modules (so I can't set up the IPC context bridge correctly).

I don't see a solution here besides enabling nodeIntegration / disabling sandbox (less secure), or simply downgrading electron :-/

Using my own preload.js is working for me. I think you may need to write it using require instead of import.

MikeJerred avatar Jan 11 '23 16:01 MikeJerred

@MikeJerred We could look into that, but trying to avoid using require if possible. I thought it was still failing for me, but haven't checked lately.

Ultimately we need to be able to use the Webpack preload.js anyway, so the first issue is still a huge blocker.

aarowman avatar Jan 11 '23 16:01 aarowman

+1

I also am having this same issue now with Electron 20, using the Webpack plugin (https://www.electronforge.io/config/plugins/webpack). My local preload script combines with webpack to a new preload.js which uses __dirname. If I go outside webpack and add my own preload ONLY, then I get an error that I cannot import outside of modules (so I can't set up the IPC context bridge correctly).

I don't see a solution here besides enabling nodeIntegration / disabling sandbox (less secure), or simply downgrading electron :-/

Checking in to see if anyone was able to get preload.js working without enabling nodeIntegration due to security concerns

bdlb77 avatar Feb 21 '23 22:02 bdlb77

+1 I also am having this same issue now with Electron 20, using the Webpack plugin (https://www.electronforge.io/config/plugins/webpack). My local preload script combines with webpack to a new preload.js which uses __dirname. If I go outside webpack and add my own preload ONLY, then I get an error that I cannot import outside of modules (so I can't set up the IPC context bridge correctly). I don't see a solution here besides enabling nodeIntegration / disabling sandbox (less secure), or simply downgrading electron :-/

Using my own preload.js is working for me. I think you may need to write it using require instead of import.

Had this issue in a pure ESM electron+forge+webpack project. For me as well, the issue was resolved by using my own preload.js in commonjs syntax instead of the preload.js bundled by webpack-plugin. nodeIntegration is disabled, sandbox and context isolation are enabled.

fetsorn avatar Feb 22 '23 12:02 fetsorn

你好朋友! 我是win10+vue 在electron 使用preload的时候我也出现了这个问题。 我开始使用preload.js也是和主线程平级的然后就发生了错误 :“Unable to load preload script” 后来我发现需要放入生成的执行文件dist_electron里才能运行成功,目前我是这样处理的。 https://blog.csdn.net/qq_31460469/article/details/129231964?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129231964%22%2C%22source%22%3A%22qq_31460469%22%7D

yesFighting avatar Feb 26 '23 13:02 yesFighting

@bdlb77 did you find any solution for this : Checking in to see if anyone was able to get preload.js working without enabling nodeIntegration due to security concerns?

VishnuRachagani avatar Mar 28 '23 14:03 VishnuRachagani

I'm getting the same error, but as soon as I change a file and reload the error goes away

the problem only happens when you first run electron forge with "npm start or yarn start", it seems electron is trying to load the preload.js file before webpack is finished building it or something like that like someone implied earlier, once it starts you need to force a reload for it to be able to load it

ferminc avatar Mar 31 '23 16:03 ferminc

I have been able to narrow this down to webpack placing a __dirname in the preload.js script that is compiled from typescript, and that by removing the plugin webpack-asset-relocator-loader its resolved - I had put it in following this comment

Jbithell avatar Apr 07 '23 12:04 Jbithell

I just hit this case with a newly created forge app.

My package.json:

{
  "name": "tlshot",
  "productName": "tlshot",
  "version": "1.0.0",
  "description": "My Electron application description",
  "main": ".webpack/main",
  "scripts": {
    "dev": "./dev.sh",
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "publish": "electron-forge publish",
    "lint": "eslint .",
    "fix": "yarn lint --fix; prettier -w .",
    "postinstall": "patch-package"
  },
  "keywords": [],
  "author": {
    "name": "Jake Teton-Landis",
    "email": "[email protected]"
  },
  "license": "MIT",
  "devDependencies": {
    "@electron-forge/cli": "^6.1.1",
    "@electron-forge/maker-deb": "^6.1.1",
    "@electron-forge/maker-rpm": "^6.1.1",
    "@electron-forge/maker-squirrel": "^6.1.1",
    "@electron-forge/maker-zip": "^6.1.1",
    "@electron-forge/plugin-webpack": "^6.1.1",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "@vercel/webpack-asset-relocator-loader": "1.7.3",
    "css-loader": "^6.0.0",
    "electron": "24.0.0",
    "electron-extension-installer": "^1.0.4",
    "eslint": "^8.0.1",
    "eslint-import-resolver-typescript": "^3.5.5",
    "eslint-plugin-import": "^2.25.0",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-unused-imports": "^2.0.0",
    "fork-ts-checker-webpack-plugin": "^7.2.13",
    "node-loader": "^2.0.0",
    "patch-package": "^6.5.1",
    "prettier": "^2.8.7",
    "style-loader": "^3.0.0",
    "ts-loader": "^9.2.2",
    "ts-node": "^10.0.0",
    "typescript": "5.0.4"
  },
  "dependencies": {
    "@tldraw/assets": "^2.0.0-canary.e59200e42",
    "@tldraw/editor": "^2.0.0-canary.e59200e42",
    "@tldraw/tldraw": "^2.0.0-canary.e59200e42",
    "@tldraw/tlstore": "^2.0.0-canary.e59200e42",
    "@tldraw/ui": "^2.0.0-canary.e59200e42",
    "@types/lodash": "^4.14.194",
    "electron-squirrel-startup": "^1.0.0",
    "electron-store": "^8.1.0",
    "execa": "^7.1.1",
    "fs-extra": "^11.1.1",
    "lodash": "^4.17.21",
    "nanoid": "^4.0.2",
    "path-browserify": "^1.0.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-new-window": "^1.0.1",
    "signia": "^0.1.2-canary.0094a5d",
    "signia-react": "^0.1.2-canary.0094a5d"
  }
}

Git repo: https://github.com/justjake/tlshot

justjake avatar Apr 15 '23 17:04 justjake