Electron+TypeScript应用中contextBridge调用auth方法报Uncaught ReferenceError
Electron + TypeScript 按钮调用后台方法报错解决
核心问题原因
Uncaught ReferenceError 本质是渲染进程无法直接访问主进程模块/方法,Electron默认开启上下文隔离(contextIsolation),渲染进程运行在独立沙箱环境,不能直接调用Node.js模块或主进程自定义代码。TypeScript编译不报错是因为编译阶段仅做类型检查,不验证Electron的进程上下文限制。
具体解决步骤
1. 配置IPC通信(主进程侧)
假设auth模块属于主进程代码,需在主进程中注册IPC监听,暴露可被渲染进程调用的方法:
// src/main/main.ts import { app, BrowserWindow, ipcMain } from 'electron'; import { login } from './auth'; // 引入auth模块的目标方法 let mainWindow: BrowserWindow | null; function createWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: `${__dirname}/preload.js`, // 必须配置预加载脚本路径 contextIsolation: true, // 保持默认开启,保障安全性 nodeIntegration: false // 保持默认关闭,避免安全风险 } }); mainWindow.loadFile('index.html'); // 注册IPC监听,处理渲染进程的登录请求 ipcMain.handle('auth:login', async (_, username, password) => { try { const result = await login(username, password); return { success: true, data: result }; } catch (err) { return { success: false, error: (err as Error).message }; } }); } app.whenReady().then(createWindow);
2. 编写预加载脚本(搭建通信桥梁)
预加载脚本运行在渲染进程上下文,但可访问Electron的IPC API,用于在渲染进程和主进程间建立安全通信通道:
// src/preload.ts import { contextBridge, ipcRenderer } from 'electron'; // 通过contextBridge向渲染进程暴露安全API contextBridge.exposeInMainWorld('electronAPI', { login: (username: string, password: string) => ipcRenderer.invoke('auth:login', username, password) });
3. 渲染进程调用暴露的API
在渲染进程的按钮点击事件中,调用预加载脚本暴露的electronAPI,而非直接引用auth模块:
// src/renderer/renderer.ts const loginBtn = document.getElementById('login-btn'); const usernameInput = document.getElementById('username') as HTMLInputElement; const passwordInput = document.getElementById('password') as HTMLInputElement; loginBtn?.addEventListener('click', async () => { const username = usernameInput.value; const password = passwordInput.value; try { // 调用预加载脚本暴露的登录方法 const result = await window.electronAPI.login(username, password); if (result.success) { console.log('登录成功:', result.data); // 处理登录成功逻辑 } else { console.error('登录失败:', result.error); } } catch (err) { console.error('调用登录接口出错:', err); } });
4. 补充TypeScript类型声明
在渲染进程的类型声明文件中添加electronAPI的类型,让TypeScript识别全局对象:
// src/renderer/types/electron-api.d.ts declare global { interface Window { electronAPI: { login: (username: string, password: string) => Promise<{ success: boolean; data?: any; error?: string; }>; }; } } export {};
5. 验证编译配置
确保tsconfig.json正确配置编译选项,比如预加载脚本的编译目标:
{ "compilerOptions": { "target": "ES2020", "module": "CommonJS", "outDir": "./dist", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules"] }
关键注意事项
- 禁止开启
nodeIntegration: true或关闭contextIsolation,这会引入严重安全风险。 - 渲染进程与主进程的所有通信必须通过
contextBridge和IPC实现,不能直接跨进程引用模块。 - 编译后需确认预加载脚本路径正确,主进程中配置的
preload需指向编译后的preload.js文件。
内容的提问来源于stack exchange,提问作者trowek
相关产品推荐
相关产品推荐

