Electron应用渲染脚本中Window对象无法获取预加载脚本数据
核心问题1:Preload脚本模块语法不匹配
你的preload.js使用了ES模块的import语法,但项目其余文件(如main.js)均采用CommonJS的require语法,且未在package.json中配置"type": "module",也没有将preload打包为ES模块格式。
Electron加载preload脚本时会直接抛出语法错误,脚本从开头就中断执行,contextBridge.exposeInMainWorld根本没有运行,自然渲染进程中不存在window.api对象。
修复方式:将preload.js的模块导入改为CommonJS格式:
const { ipcRenderer, contextBridge } = require("electron");
核心问题2:隔离上下文下直接修改window属性无效
你在preload中写的window.isWorking = true无法被渲染进程识别,原因是开启contextIsolation: true后,preload运行的上下文和渲染进程的上下文是完全隔离的两个独立环境,preload里的window对象并不是渲染进程实际使用的全局对象,直接赋值不会同步到渲染侧。
如果需要暴露自定义属性到渲染进程,必须通过contextBridge.exposeInMainWorld实现,不能直接给preload的window赋值。比如要暴露isWorking属性,可以直接在暴露对象中添加字段:
contextBridge.exposeInMainWorld( "api", { isWorking: true, send: (channel, data) => { let validChannels = ["test"]; if (validChannels.includes(channel)) { ipcRenderer.send(channel, data); } }, receive: (channel, func) => { let validChannels = ["test"]; if (validChannels.includes(channel)) { ipcRenderer.on(channel, (event, ...args) => func(...args)); } } } );
规范优化
preload路径建议使用绝对路径拼接,避免相对路径解析失败(尤其是打包后场景),修改main.js中的webPreferences配置:
webPreferences: { contextIsolation: true, nodeIntegration: false, enableRemoteModule: false, preload: path.join(__dirname, 'preload.js') }
验证方式
可以在preload脚本的最开头加一行console.log('preload执行正常'),启动应用后查看主进程终端的输出,确认preload脚本是否被正常加载执行。
完成上述修改后,渲染进程即可正常访问
window.api对象,IPC通信链路可正常运行。
内容的提问来源于stack exchange,提问作者Vincent Kenbeek

