Electron的webPreferences常用配置详解
详解webPreferences的contextIsolation和nodeIntegration配置
preload配置项
ebPreferences有个preload配置项:preload: path.join(__dirname, 'preload.js')
用来配置预加载脚本,用于向渲染进程暴露有限 API
示例代码:
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
getAppInfo: () => ipcRenderer.invoke('get-app-info'),
});
contextIsolation和nodeIntegration
这两个配置如果完全不设置时等价于:
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
}
关于contextIsolation
控制 Electron 内部是否把页面 JS 世界和 preload 脚本世界隔离开。 true(推荐默认值):两个世界分开,页面不能直接碰到 preload 里注入的东西,必须通过 contextBridge 暴露 false:不隔离,页面和 preload 共享同一个 JS 环境
两个“世界”
开启 contextIsolation: true 后,渲染进程里会有两个独立的 JavaScript 上下文:
┌─────────────────────────────────────────┐
│ 渲染进程 (Renderer) │
│ │
│ ┌─────────────────┐ ┌──────────────┐ │
│ │ Isolated World │ │ Main World │ │
│ │ (隔离世界) │ │ (主世界) │ │
│ │ │ │ │ │
│ │ preload.js │ │ renderer.js │ │
│ │ ✅ require() │ │ ❌require() │ │
│ │ ✅ Node API │ │ 像普通网页 │ │
│ └─────────────────┘ └──────────────┘ │
└─────────────────────────────────────────┘
- Isolated World:preload.js 在这里跑,可以用 require、Node API
- Main World:index.html 里 <script src=“renderer.js”> 在这里跑,行为和 Chrome 网页里的 JS 一样
两者互不可见:renderer.js 拿不到 preload 里的变量,preload 也碰不到页面里的 window 对象(除非用 contextBridge 主动暴露)。
如果关掉隔离:contextIsolation: false
这时只有一个世界,页面和 preload 共享环境,如果此时又把nodeIntegration: true开启了,那么页面的 renderer.js 就能直接使用NODE APi,IPC 在 renderer.js 里直接写就行,此时preload.js就没有什么必要了。
但是,如果关掉隔离,那么页面一旦被注入恶意 JS,就能直接 require(‘child_process’) 执行系统命令,就不安全了。故官方推荐推荐默认应开启。
关于nodeIntegration配置
允许渲染进程里的页面脚本使用 Node.js API,例如:const { ipcRenderer } = require(‘electron’) true:页面里可以用 require、process、Buffer 等 false:页面像普通浏览器网页,不能直接用 Node
总结:
- 必须
nodeIntegration: true+contextIsolation: false页面才可以使用node api - preload.js文件始终能使用node api,不受到nodeIntegration影响
- 满足
nodeIntegration: flase和contextIsolation: true任意一个,页面都不能直接使用node api
在现代 Electron 项目里,preload.js 几乎是标准做法,尤其是页面要和主进程通信时。reload.js 是页面和主进程之间的安全桥梁,只暴露必要 API,而不是把整个 Node/Electron 权限交给页面。