forge
forge copied to clipboard
Unable to load preload script
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

Steps to reproduce
check the code at https://github.com/mikesongming/electron-forge-demo.git
Additional information
No response
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,
},
});
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/
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.
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.
__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
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
},
});
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:

can you double check that the demo leads us to the correct error message? 🥂
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
Seems to me I am not getting the error on Ubuntu 22.04
Weird... Could be a windows bug?
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
looks like preload is loaded before it's done build, when i save package.json everything works normally.
without contextIsolation
& nodeIntegrationInWorker
enabled
@georgexu99
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 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/
@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
@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.
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!
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.
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 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.
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 setsandbox: 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!
+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 :-/
+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 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.
+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
+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 enablingnodeIntegration
/ 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 usingrequire
instead ofimport
.
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.
你好朋友! 我是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
@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?
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
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
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