Electron Forge中ipcRenderer的使用

记录一次在Electron Forge中render端使用ipcRenderer与mian进程通信的踩坑经历。

由于能查到的中文资料较少,但是Electron Forge官方文档说的也不是很清楚,如果你也遇到了和我同样的问题,希望对你有帮助。

目前(2021年8月29日),Electron有两种使用icpRenderer与主进程通信的方式:

  1. 在创建window的时候配置:nodeIntegration: true,然后在UI端就可以
import {ipcRenderer} from 'electron';
  1. 是使用官方推荐的contextIsolation。需要一个中介:preload.js。

于是我一个个尝试:

尝试nodeIntegration

第一步:按照Electron官网要求

const mainWindow = new BrowserWindow({
    height: 600,
    width: 800,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

第二步:在render进程引入ipcRenderer

import {ipcRenderer} from 'electron';
...
ipcRenderer.send("hi");
...

结果:不行。

尝试contextIsolation

第一步:创建preload.js,并利用contextBridge桥接全局变量(render端可以直接访问)

const { contextBridge, ipcRenderer } = require('electron');
// import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('electron', {
  ipcRenderer: {
    hi() {
      ipcRenderer.send('hi');
    },
  },
});

第二步:main中创建window时导入preload.js

 const mainWindow = new BrowserWindow({
    height: 600,
    width: 800,
    webPreferences: {
      preload: path.join(__dirname,"preload.js")
    },
  });

第三部:在render端使用

window.electron.ipcRenderer.hi();

结果:失败。
1.由于使用了typescript,说我window上没有electron属性,所以改为:

const electron = (window as any).electron ? (window as any).electron : {send:()=>{}};

2.骗过typescript了,但是没啥反应,查看devtools说electron是undefined。怀疑引入preload.js没成功。所以开始各种改路径。


中间各种折腾这里不再赘述,最后通过官方文档加github中的几个issue把这两个问题都解决了,直接出结论:

第一种:直接在UI端import icpRenderer

如果你使用nodeIntegration:true的方式,即在UI端直接import ‘electron’的方式,请确保以下关键步骤正确:

  1. 创建window时设置:
webPreferences: {
   nodeIntegration: true,
   contextIsolation: false,
},

2.同时在package.json中设置

...
"config": {
    "forge": {
        ...
      "plugins": [
         [
          "@electron-forge/plugin-webpack",
          {
          ...
          "entryPoints": [
                {
                  "html": "./src/index.html",
                  "js": "./src/renderer.ts",
                  "name": "main_window",
                }
              ],
          "nodeIntegration": true // 重点:在这里也要设置true
          ...
...

第二种:使用Context Isolation的方式(preload)

官方推荐使用该方式,因为nodeIntegration存在一定安全风险。
关键步骤如下:

  1. 在主进程(ElectronForge目录中为index.ts)
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY : string;
...
  const mainWindow = new BrowserWindow({
    height: 600,
    width: 800,
    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY
    },
  });
...

2.在package.json中设置entry points

["@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.js"           // 这里是重点(看准位置哦)
          }                                    //
        }
      ],
    }
  }
]

如果你没看懂或者还是有问题,也可以私信我,我们一起研究。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容