使用 electron ipc 时,Electron forge 停止遵守渲染器代码
Electron forge stopped in complies renderer code when using electron ipc
我正在创建一个新的 Electron 应用程序,但我遇到了一个从未遇到过的问题
我用了import {ipcRenderer} from 'electron'
,用了ipcRenderer.send
,在编译Renderer Code的时候显示这个错误
在最新的 electron 和 electron forge 中,导入 electron 并在任何渲染器代码中使用它都会导致错误并终止
我在electron里用的是React,我之前的项目也是用的React+Electron,不过用electron模块没问题
我能做的所有事情都不起作用,包括降级电子包。
完整日志:
yarn run v1.22.10
$ electron-forge start
√ Checking your system
√ Locating Application
√ Preparing native dependencies
√ Compiling Main Process Code
√ Launch Dev Servers
√ Compiling Preload Scripts
√ Launching Application
Webpack Output Available: http://localhost:9000
\ Compiling Renderer Code
An unhandled rejection has occurred inside Forge:
[Error: EISDIR: illegal operation on a directory, read] {
errno: -4068,
code: 'EISDIR',
syscall: 'read'
}
Electron Forge was terminated. Location:
{}
error Command failed with exit code 1.
我尝试重新安装所有软件包,但没有用。
为什么以及如何解决?
即使我在webpack.renderer.config.json中添加了一个target: 'node'
,哦window终于可以显示了,但是ipcRender CANNOT send message
Uncaught TypeError: Cannot read property 'send' of undefined
at onClick (TitleBar.tsx?3219:11)
at HTMLUnknownElement.callCallback (react-dom.development.js?6ac8:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js?6ac8:3994)
at invokeGuardedCallback (react-dom.development.js?6ac8:4056)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?6ac8:4070)
at executeDispatch (react-dom.development.js?6ac8:8243)
at processDispatchQueueItemsInOrder (react-dom.development.js?6ac8:8275)
at processDispatchQueue (react-dom.development.js?6ac8:8288)
at dispatchEventsForPlugins (react-dom.development.js?6ac8:8299)
at eval (react-dom.development.js?6ac8:8508)
为什么????
我遇到了同样的问题,仍然卡在这个
更新:使用preload.js访问主进程的功能
我遇到了同样的问题。我正在使用 Webpack + React
经过调查,我认为是因为webpack bundle的问题。我们甚至不能使用包 @electron/remote
这是我的解决方法。我在 preload.ts
中创建了一个函数
Remember to use import * as electron from 'electron';
import * as electron from 'electron';
export function openDirectory(): void {
const dialog = (electron as any).remote.dialog;
console.log(
dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })
);
}
通过contextBridge
曝光
import { contextBridge } from 'electron';
import { getGitCommitLogs } from './core/git-api';
import { openDirectory } from './core/native-api';
contextBridge.exposeInMainWorld('getGitCommitLogs', getGitCommitLogs);
contextBridge.exposeInMainWorld('openDirectory', openDirectory);
在渲染器中使用它
启用enableRemoteModule
const mainWindow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
enableRemoteModule: true,
},
});
I have posted my source code and issue
https://github.com/electron-userland/electron-forge/issues/2384
解决方案是使用 electron
中的 ContextBridge
API for electron-forge react+webpack 模板
preload.js
import { ipcRenderer, contextBridge } from "electron";
contextBridge.exposeInMainWorld("electron", {
notificationApi: {
sendNotification(message) {
ipcRenderer.send("notify", message);
},
},
batteryApi: {},
fileApi: {},
});
main.js
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
worldSafeExecuteJavaScript: true,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},
});
ipcMain.on("notify", (_, message) => {
new Notification({ title: "Notification", body: message }).show();
});
package.json
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.js",
"name": "main_window",
"preload": {
"js": "./src/preload.js"
}
}
]
}
}
]
]
app.jsx
import * as React from "react";
import * as ReactDOM from "react-dom";
class App extends React.Component {
componentDidMount() {
electron.notificationApi.sendNotification("Finally!");
}
render() {
return <h1>contextBridge</h1>;
}
}
ReactDOM.render(<App />, document.body);
tl;博士
让webpack明白electron应该使用require
直接导入
解决方案
这是一个 webpack 问题。
Webpack 会将所有使用到的包打包成 bundle。因为 electron 是一个超酷 包,webpack 可以不能 将其打包。
像这样配置使电子成为commonjs2模块,直接从import electron from 'electron
到require('electron')
声明而不是从电子中获取项目。
// webpack.renderer.config.js
module.exports = {
externals: {
electron: 'commonjs2 electron',
},
}
我正在创建一个新的 Electron 应用程序,但我遇到了一个从未遇到过的问题
我用了import {ipcRenderer} from 'electron'
,用了ipcRenderer.send
,在编译Renderer Code的时候显示这个错误
在最新的 electron 和 electron forge 中,导入 electron 并在任何渲染器代码中使用它都会导致错误并终止
我在electron里用的是React,我之前的项目也是用的React+Electron,不过用electron模块没问题
我能做的所有事情都不起作用,包括降级电子包。
完整日志:
yarn run v1.22.10
$ electron-forge start
√ Checking your system
√ Locating Application
√ Preparing native dependencies
√ Compiling Main Process Code
√ Launch Dev Servers
√ Compiling Preload Scripts
√ Launching Application
Webpack Output Available: http://localhost:9000
\ Compiling Renderer Code
An unhandled rejection has occurred inside Forge:
[Error: EISDIR: illegal operation on a directory, read] {
errno: -4068,
code: 'EISDIR',
syscall: 'read'
}
Electron Forge was terminated. Location:
{}
error Command failed with exit code 1.
我尝试重新安装所有软件包,但没有用。
为什么以及如何解决?
即使我在webpack.renderer.config.json中添加了一个target: 'node'
,哦window终于可以显示了,但是ipcRender CANNOT send message
Uncaught TypeError: Cannot read property 'send' of undefined
at onClick (TitleBar.tsx?3219:11)
at HTMLUnknownElement.callCallback (react-dom.development.js?6ac8:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js?6ac8:3994)
at invokeGuardedCallback (react-dom.development.js?6ac8:4056)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js?6ac8:4070)
at executeDispatch (react-dom.development.js?6ac8:8243)
at processDispatchQueueItemsInOrder (react-dom.development.js?6ac8:8275)
at processDispatchQueue (react-dom.development.js?6ac8:8288)
at dispatchEventsForPlugins (react-dom.development.js?6ac8:8299)
at eval (react-dom.development.js?6ac8:8508)
为什么????
我遇到了同样的问题,仍然卡在这个
更新:使用preload.js访问主进程的功能
我遇到了同样的问题。我正在使用 Webpack + React
经过调查,我认为是因为webpack bundle的问题。我们甚至不能使用包 @electron/remote
这是我的解决方法。我在 preload.ts
Remember to use
import * as electron from 'electron';
import * as electron from 'electron';
export function openDirectory(): void {
const dialog = (electron as any).remote.dialog;
console.log(
dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })
);
}
通过contextBridge
import { contextBridge } from 'electron';
import { getGitCommitLogs } from './core/git-api';
import { openDirectory } from './core/native-api';
contextBridge.exposeInMainWorld('getGitCommitLogs', getGitCommitLogs);
contextBridge.exposeInMainWorld('openDirectory', openDirectory);
在渲染器中使用它
启用enableRemoteModule
const mainWindow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
enableRemoteModule: true,
},
});
I have posted my source code and issue https://github.com/electron-userland/electron-forge/issues/2384
解决方案是使用 electron
中的 ContextBridge
API for electron-forge react+webpack 模板
preload.js
import { ipcRenderer, contextBridge } from "electron";
contextBridge.exposeInMainWorld("electron", {
notificationApi: {
sendNotification(message) {
ipcRenderer.send("notify", message);
},
},
batteryApi: {},
fileApi: {},
});
main.js
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
worldSafeExecuteJavaScript: true,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},
});
ipcMain.on("notify", (_, message) => {
new Notification({ title: "Notification", body: message }).show();
});
package.json
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.js",
"name": "main_window",
"preload": {
"js": "./src/preload.js"
}
}
]
}
}
]
]
app.jsx
import * as React from "react";
import * as ReactDOM from "react-dom";
class App extends React.Component {
componentDidMount() {
electron.notificationApi.sendNotification("Finally!");
}
render() {
return <h1>contextBridge</h1>;
}
}
ReactDOM.render(<App />, document.body);
tl;博士
让webpack明白electron应该使用require
直接导入
解决方案
这是一个 webpack 问题。
Webpack 会将所有使用到的包打包成 bundle。因为 electron 是一个超酷 包,webpack 可以不能 将其打包。
像这样配置使电子成为commonjs2模块,直接从import electron from 'electron
到require('electron')
声明而不是从电子中获取项目。
// webpack.renderer.config.js
module.exports = {
externals: {
electron: 'commonjs2 electron',
},
}