Electron点击按钮加载EJS视图失败,提示无法加载本地资源
Electron点击按钮无法打开EJS视图的问题解决
问题重现
在Electron应用中,点击按钮尝试打开EJS视图,前端通过window.location="/whouseExit"跳转,主进程用Express配置了/whouseExit路由处理数据库查询并渲染EJS,但点击后报错:Not allowed to load local resource: file:///C:/whouseExit。
前端点击事件代码
document.getElementById('goto-exitW-button').addEventListener('click', () => { window.location="/whouseExit"; });
主进程main.js路由代码片段
appExpress.get("/whouseExit",(req,res) => { var Connection = require('tedious').Connection; var Request = require('tedious').Request; var config = { server: 'localhost', authentication: { type: 'default', options: { userName: 'sa', password: '42345243', }, }, options: { encrypt: false, database: 'cusst', }, }; const connection = new Connection(config); connection.connect((err) => { if (err) { console.log('Connection Failed'); throw err; } executeStatement() .then((myRows) => { res.render('whouseExitejs.ejs', { myRows }); }) .catch((error) => { console.error(error); }); }); function executeStatement() { // database stuff .... } });
核心错误原因
Electron渲染进程初始加载的是本地文件(如file:///xxx/index.html),此时使用相对路径/whouseExit会被解析为本地文件系统路径,而非向Express服务器发起HTTP请求,因此触发本地资源加载限制报错。
解决方案
方案1:直接请求Express渲染的HTTP页面
- 确保Express服务器已启动并监听指定端口(如3000),在main.js末尾添加:
appExpress.listen(3000, () => { console.log('Express server running on http://localhost:3000'); }); - 修改前端跳转代码,使用完整HTTP URL:
document.getElementById('goto-exitW-button').addEventListener('click', () => { window.location = 'http://localhost:3000/whouseExit'; }); - 配置Electron允许加载外部资源:
创建BrowserWindow时,在webPreferences中调整配置(开发环境可临时关闭webSecurity,生产环境需配置contentSecurityPolicy):const mainWindow = new BrowserWindow({ webPreferences: { webSecurity: false, // 开发环境用,生产环境替换为contentSecurityPolicy // 生产环境示例: // contentSecurityPolicy: "default-src 'self' http://localhost:3000;" } });
方案2:使用Electron IPC通信(推荐,符合Electron架构)
这种方式遵循主进程-渲染进程分离原则,数据库操作放在主进程,渲染进程通过IPC通知跳转。
主进程(main.js)修改:
const { ipcMain, BrowserWindow } = require('electron'); const path = require('path'); // 监听渲染进程的跳转请求 ipcMain.on('navigate-to-whouseExit', async (event) => { try { // 执行数据库查询(复用原有逻辑) const myRows = await executeStatement(); // 创建新窗口加载Express渲染的页面,或直接在当前窗口加载 const newWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { contextIsolation: true, nodeIntegration: false } }); // 加载Express渲染后的页面 newWindow.loadURL('http://localhost:3000/whouseExit'); } catch (err) { console.error(err); event.reply('navigate-error', '加载失败:' + err.message); } }); // 封装数据库查询为异步函数 async function executeStatement() { // 原有数据库操作逻辑,返回myRows return new Promise((resolve, reject) => { // 这里写具体的查询代码,成功时resolve(myRows),失败时reject(err) }); } // 启动Express服务器 appExpress.listen(3000);渲染进程(前端代码)修改:
const { ipcRenderer } = require('electron'); document.getElementById('goto-exitW-button').addEventListener('click', () => { ipcRenderer.send('navigate-to-whouseExit'); }); // 监听主进程的错误反馈 ipcRenderer.on('navigate-error', (event, msg) => { alert(msg); });
额外注意事项
- 确认Express视图目录配置正确:
appExpress.set('views', path.join(__dirname, 'views')); // 指定views文件夹绝对路径 appExpress.set('view engine', 'ejs'); - 数据库操作完成后要关闭连接,避免资源泄漏;
- 生产环境不要使用
webSecurity: false,需配置合法的contentSecurityPolicy限制资源加载范围。
内容的提问来源于stack exchange,提问作者MrB
相关产品推荐
相关产品推荐

