【问题标题】:Electron Forge - Can't use ipcRenderer in the renderer fileElectron Forge - 无法在渲染器文件中使用 ipcRenderer
【发布时间】:2020-10-09 12:29:37
【问题描述】:

我刚刚使用以下命令创建了一个新应用程序:

npx create-electron-app my-new-app --template=typescript-webpack

renderer.ts 我添加了以下代码

import "./index.css";
import { ipcRenderer } from "electron";

但是当我运行 npm run start 我在浏览器控制台中出现以下错误

Uncaught ReferenceError: require is not defined

更新 我试过的:

webpack.plugins.js

const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const webpack = require("webpack");
module.exports = [
  new ForkTsCheckerWebpackPlugin(),
  new webpack.ExternalsPlugin("commonjs", ["electron"]),
];

但还是不行。

【问题讨论】:

    标签: node.js electron electron-forge


    【解决方案1】:

    找到解决方案

    解决方案是在预加载脚本中使用 ipcRenderer。

    preload.ts

    import { ipcRenderer } from "electron";
    

    index.ts

    declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: any;
    
    const mainWindow = new BrowserWindow({
      height: 600,
      width: 800,
      webPreferences: {
        preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
      },
    });
    

    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.ts",
                  "name": "main_window",
                  "preload": {
                    "js": "./src/preload.ts"
                  }
                }
              ]
            }
          }
        ]
      ]
    

    【讨论】:

    • George,您可能需要添加“声明 const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: any;”作为 Typescript 用户的注释,否则他们会收到错误,因为 TS 编译器不会知道这个 Global。这可以在主 index.ts 中定义,或者您可以在创建全局声明后将这些“声明”声明(包括默认值)移动到“src/typings.d.ts”中 { // your declare const....here }。如果你希望我可以为你编辑这个:)
    • 你如何在应用程序中引用 ipcRenderer? (例如 React 组件?)
    • @BlueWaters 要从 React 组件发送 IPC 消息,您必须增强 preload.ts 脚本: import { contextBridge, ipcRenderer } from 'electron'; contextBridge.exposeInMainWorld('dog', { bark(arg1, arg2) { ipcRenderer.invoke('dog.bark', arg1, arg2); } });现在你的 React 组件中有一个 window.dog.bark() 函数可用。
    • 我即将实施此解决方案。我已经在上下文桥中定义了我的函数,并且可以从调试控制台(如window.api.get())调用它。但是,在我的 react typescript 组件中,我不断收到window.api is not a function。如何声明新函数?
    • 嗨@EvanLalo!如果您使用window.api,我假设您的预加载脚本中有类似的内容:contextBridge.exposeInMainWorld("api",{}) 对吗?
    【解决方案2】:

    解决方案是使用来自electronContextBridge API 用于电子锻造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);
    

    【讨论】:

    • 这正是我正在寻找的......非常感谢你回答这个兄弟。欣赏它
    【解决方案3】:

    如果您使用的是 typescript,则需要将其添加到您的 renderer.ts 文件中:

    declare global {
      interface Window {
        electron: {
          funcName: () => void;
        };
      }
    }
    

    那么你可以使用window.electron.funcName()

    【讨论】:

      【解决方案4】:

      在 index.js 中创建新窗口时使用

      win = new BrowserWindow({
              webPreferences: {
                  preload: path.join(__dirname, 'app', 'assets', 'js', 'preloader.js'),
                  nodeIntegration: true,
                  contextIsolation: false
              },
          })
      

      只需将nodeIntegration: true 添加到webPreferences。然后您就可以使用require

      【讨论】:

      • ** nodeIntegration: true** 由于安全原因,不推荐使用
      • 不要在这里堆砌,但@GeorgianStan 是正确的,最好不要启用nodeIntegration。他上面的例子是正确的答案。
      猜你喜欢
      • 2017-11-04
      • 2022-01-27
      • 1970-01-01
      • 2023-03-10
      • 2018-11-12
      • 2020-08-31
      • 2021-07-22
      • 2017-01-12
      • 1970-01-01
      相关资源
      最近更新 更多