Electron踩坑笔记——require is not defined

Electron作为一个跨平台的前端框架,已经闻名好多年了,现在开始学习可能显得有点晚,不过迟到总比没有强,从现在开始一步一步的学吧。

遇到问题

开发的第一个demo,是参考的网上找的教程。

可能是这个教程出的还比较早,在跟随教程步骤开发时,Electron窗口虽然打开了,但里面一直没有内容。后来通过调试工具发现报了一个require is not defined错误。

require is not defined错误

require is not defined错误

问题原因

由于require可以直接请求运行客户机上的文件,容易引起安全问题,而在Electron 12以后的版本中被禁止。Electron官方文档原文如下:

上下文隔离功能将确保您的 预加载脚本 和Electron的内部逻辑 运行在所加载的webcontent网页 之外的另一个独立的上下文环境里。 这对安全性很重要,因为它有助于阻止网站访问Electron的内部组件 和 您的预加载脚本可访问的高等级权限的API 。
这意味着,实际上,您的预加载脚本访问的window对象并不是网站所能访问的对象。例如,如果您在预加载脚本中设置window.hello = 'wave'并且启用了上下文隔离,当网站尝试访问window.hello对象时将返回undefined
Electron 12以来,默认情况下已启用上下文隔离,并且它是 所有应用程序推荐的安全设置。

解决方案

如果需要直接饮用客户机上的文件,则需要设置web上下文contextIsolation选项为false

1
2
3
4
5
6
7
8
9
10
11
12
app.on("ready", () => {
win = new BrowserWindow({
width: 300,
height: 300,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
})
win.loadFile("./index.html")
handleIPC()
})

修改后,本地使用require时,程序就正常跑起来了。

程序就正常跑起来了

程序就正常跑起来了

影响

不过,看官方文档描述,并没有提到require的问题,由此不难分析出,这么设置并不是针对解决这个问题的,而是解决上下文隔离的问题,那这样的话,修改了contextIsolation的值,必然会影响到上下文隔离相关的API。具体来说,就是contextBridge API将不能使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//修改前
const { contextBridge, ipcRenderer } = require('electron')
const path = require('path')

contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)

//修改后
const { ipcRenderer } = require('electron')
const path = require('path')
function doThing(fileName) {
ipcRenderer.send('do-a-thing', path.join(process.cwd(), fileName))
}

本文永久链接: https://www.mulianju.com/electron-note__require/