Open mikesongming opened 2 years ago
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
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? 🥂
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.
@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.
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": "just.1.jake@gmail.com"
},
"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
Here's a fresh repro of the error in a newly-created electron-forge
project:
I created this project via: yarn create electron-app preload-error-repro --template=webpack-typescript
Then, I added some imports to preload.ts
:
diff --git a/forge.config.ts b/forge.config.ts
index e356488..75f684a 100644
--- a/forge.config.ts
+++ b/forge.config.ts
@@ -15,6 +15,7 @@ const config: ForgeConfig = {
plugins: [
new WebpackPlugin({
mainConfig,
+ port: 5001,
renderer: {
config: rendererConfig,
entryPoints: [
diff --git a/src/preload.ts b/src/preload.ts
index 5e9d369..93aeaad 100644
--- a/src/preload.ts
+++ b/src/preload.ts
@@ -1,2 +1,26 @@
// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
+
+try {
+ console.log("preload.ts can access __dirname:", __dirname);
+} catch (error) {
+ console.error("preload.ts cannot access __dirname:", error);
+}
+
+import { contextBridge } from "electron";
+import child_process from "child_process";
+import path from "path";
+console.log("preload.ts can import node modules:", { child_process, path }});
+
+const preloadStuff = {
+ child_process,
+ join: path.join,
+} as const;
+
+contextBridge.exposeInMainWorld("fromPreload", preloadStuff);
+
+declare global {
+ interface Window {
+ fromPreload: typeof preloadStuff;
+ }
+}
diff --git a/src/renderer.ts b/src/renderer.ts
index a91994f..5754360 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -26,6 +26,13 @@
* ```
*/
-import './index.css';
+import "./index.css";
-console.log('👋 This message is being logged by "renderer.js", included via webpack');
+console.log(
+ '👋 This message is being logged by "renderer.js", included via webpack'
+);
+console.log(
+ "fromPreload:",
+ window.fromPreload,
+ window.fromPreload.join("a", "b", "c")
+);
Repo: https://github.com/justjake/electron-forge-webpack-preload-error-repro
Ah, I think for __dirname
and node modules to work in preload, you need to set sandbox: false
(and probably then contextIsolation: true
to maintain security while allowing complete node integration in the preload?
Can we expect an update from the team? Or any way to securely do it. Currently I am enabling the nodeIntegrationInWorker to resolve this "__dirname is not defined" and to make contextBridge and ipc work correctly.
I 'fixed' it by patching @electron-forge/plugin-webpack
so it also strips __dirname
from preloads
(I do not know if this is safe)
diff --git a/dist/WebpackConfig.js b/dist/WebpackConfig.js
index a0e876ea373009554472cada07f1b80a38444ed7..c82403b9cd36d4ea67238648289a3062459bea30 100644
--- a/dist/WebpackConfig.js
+++ b/dist/WebpackConfig.js
@@ -142,6 +142,7 @@ class WebpackConfigGenerator {
__dirname: false,
__filename: false,
},
+ plugins: [new AssetRelocatorPatch_1.default(this.isProd, !!this.pluginConfig.renderer.nodeIntegration)],
}, rendererConfig || {}, { target: 'electron-preload' });
}
async getRendererConfig(entryPoints) {
Does anyone have a solution for this? It's 2024 and I'm still stuck on Electron 19.
Does anyone have a solution for this? It's 2024 and I'm still stuck on Electron 19.
Yes it was fixed in the forge webpack plugin, this issue should be resolved
Yes it was fixed in the forge webpack plugin, this issue should be resolved
I just updated my project to the latest electron but I still get the error;
VM4 sandbox_bundle:2 Unable to load preload script: C:\Users\...\server\src\js\preload.js
What should I do to fix it?
I'm seeing this error --
"devDependencies": { "@babel/core": "^7.24.4", "@babel/preset-react": "^7.24.1", "@electron-forge/cli": "^7.4.0", "@electron-forge/maker-deb": "^7.4.0", "@electron-forge/maker-rpm": "^7.4.0", "@electron-forge/maker-squirrel": "^7.4.0", "@electron-forge/maker-zip": "^7.4.0", "@electron-forge/plugin-auto-unpack-natives": "^7.4.0", "@electron-forge/plugin-fuses": "^7.4.0", "@electron-forge/plugin-webpack": "^7.4.0", "@electron/fuses": "^1.8.0", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@vercel/webpack-asset-relocator-loader": "^1.7.3", "babel-loader": "^9.1.3", "css-loader": "^6.11.0", "electron": "30.0.0", "node-loader": "^2.0.0", "style-loader": "^3.3.4" },
Tenía el mismo problema, lo resolví usando la extensión ".mjs" -> "preload.mjs". No fué necesario tocar nada más.
I had the same problem, I solved it by using the extension ".mjs" -> "preload.mjs". It was not necessary to touch anything else.
Maybe it is not exactly this issue, however I had similar error after updating electron/forge from 6 to 7.4
forge.config.js stopped to generate preload.js file inside .webpack folder and I was struggling with it for a day...
I am using loadUrl that is why I didn't have html file in my entryPoints, after I created html file and added it to forge.config.js, my preload.js file starts generating in .webpack/renderer/main_window/preload.js
...
Yes, right now I have useless html file, but it works!
plugins: [
{
name: '@electron-forge/plugin-webpack',
config: {
mainConfig: path.resolve(__dirname, 'webpack.main.config.js'),
renderer: {
config: path.resolve(__dirname, 'webpack.renderer.config.js'),
entryPoints: [
{
html: './src/index.html', // << you had to include this line!
js: path.resolve(__dirname, 'src/renderer.ts'),
name: 'main_window',
preload: {
js: path.resolve(__dirname, 'src/preload.ts'),
}
}
]
},
}
}
],
Pre-flight checklist
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