記錄一次在Electron Forge中render端使用ipcRenderer與mian進程通信的踩坑經(jīng)歷。
由于能查到的中文資料較少,但是Electron Forge官方文檔說的也不是很清楚,如果你也遇到了和我同樣的問題,希望對你有幫助。
目前(2021年8月29日),Electron有兩種使用icpRenderer與主進程通信的方式:
- 在創(chuàng)建window的時候配置:nodeIntegration: true,然后在UI端就可以
import {ipcRenderer} from 'electron';
- 是使用官方推薦的contextIsolation。需要一個中介:preload.js。
于是我一個個嘗試:
嘗試nodeIntegration
第一步:按照Electron官網(wǎng)要求
const mainWindow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
第二步:在render進程引入ipcRenderer
import {ipcRenderer} from 'electron';
...
ipcRenderer.send("hi");
...
結(jié)果:不行。
嘗試contextIsolation
第一步:創(chuàng)建preload.js,并利用contextBridge橋接全局變量(render端可以直接訪問)
const { contextBridge, ipcRenderer } = require('electron');
// import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: {
hi() {
ipcRenderer.send('hi');
},
},
});
第二步:main中創(chuàng)建window時導(dǎo)入preload.js
const mainWindow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
preload: path.join(__dirname,"preload.js")
},
});
第三部:在render端使用
window.electron.ipcRenderer.hi();
結(jié)果:失敗。
1.由于使用了typescript,說我window上沒有electron屬性,所以改為:
const electron = (window as any).electron ? (window as any).electron : {send:()=>{}};
2.騙過typescript了,但是沒啥反應(yīng),查看devtools說electron是undefined。懷疑引入preload.js沒成功。所以開始各種改路徑。
中間各種折騰這里不再贅述,最后通過官方文檔加github中的幾個issue把這兩個問題都解決了,直接出結(jié)論:
第一種:直接在UI端import icpRenderer
如果你使用nodeIntegration:true的方式,即在UI端直接import ‘electron’的方式,請確保以下關(guān)鍵步驟正確:
- 創(chuàng)建window時設(shè)置:
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
2.同時在package.json中設(shè)置
...
"config": {
"forge": {
...
"plugins": [
[
"@electron-forge/plugin-webpack",
{
...
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.ts",
"name": "main_window",
}
],
"nodeIntegration": true // 重點:在這里也要設(shè)置true
...
...
第二種:使用Context Isolation的方式(preload)
官方推薦使用該方式,因為nodeIntegration存在一定安全風險。
關(guān)鍵步驟如下:
- 在主進程(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中設(shè)置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" // 這里是重點(看準位置哦)
} //
}
],
}
}
]
如果你沒看懂或者還是有問題,也可以私信我,我們一起研究。