Electron-Vite+React生产环境加载video.html本地资源失败求助
Electron-Vite + React生产环境加载第二个BrowserWindow的video.html失败问题
基于Electron-Vite + React开发应用,开发环境执行npm run dev时能正常在第二个BrowserWindow加载本地video.html,但切换到生产环境预览(执行npm start)时,调用loadFile或loadURL都会抛出“Unable to load local resource”错误,主窗口加载index.html则完全正常。
主进程文件index.js
import { app, shell, BrowserWindow, ipcMain } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' let mainWindow, secondWindow function createWindow() { mainWindow = new BrowserWindow({ width: 900, height: 670, show: false, autoHideMenuBar: true, ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, contextIsolation: true, enableRemoteModule: false, webSecurity: true } }) mainWindow.on('ready-to-show', () => { mainWindow.show() }) mainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/index.html`) } else { mainWindow.loadFile(join(__dirname, '../renderer/index.html')) } } function createSecondWindow() { secondWindow = new BrowserWindow({ width: 1080, height: 720, autoHideMenuBar: true, ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, contextIsolation: true, enableRemoteModule: false, webSecurity: true } }) secondWindow.on("ready-to-show", () => { secondWindow.show(); }); secondWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) if (is.dev && process.env['ELECTRON_RENDERER_URL']) { secondWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/video.html`) } else { secondWindow.loadFile(join(__dirname, '../renderer/video.html')); } } app.whenReady().then(() => { electronApp.setAppUserModelId('com.electron') app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window) }) createWindow() createSecondWindow() app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) ipcMain.on("play-video", (event, videoPath) => { if (secondWindow) { secondWindow.webContents.send("start-video", videoPath); } })
Electron.vite.config.js
import { resolve } from 'path' import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import react from '@vitejs/plugin-react' export default defineConfig({ main: { plugins: [externalizeDepsPlugin()] }, preload: { plugins: [externalizeDepsPlugin()] }, renderer: { resolve: { alias: { '@renderer': resolve('src/renderer/src') } }, plugins: [react()] }, })
应用结构
├── build ├── out └─┬ src ├── preload ├─┬ main │ └── index.js ├─┬ renderer │ ├── index.html │ ├── video.html │ ├── public │ └─┬ src │ ├── App.jsx (React component used in main.jsx) │ ├── VideoApp.jsx (React component used in video.jsx) │ ├── main.jsx (src for index.html) │ └── video.jsx (src for video.html) ├── electron.vite.config.js └── package.json
已尝试方案
- 使用
loadFile和loadURL方法加载video.html,均出现相同错误 - 调整Electron的
webSecurity等安全配置,问题仍未解决
解决方案
核心问题
Electron-Vite默认仅将index.html作为渲染入口打包,生产环境下video.html没有被复制到输出目录,导致loadFile找不到对应文件。
修复步骤
- 修改electron.vite.config.js,配置多页面入口
在renderer的build选项中添加rollupOptions.input,显式指定所有需要打包的HTML文件:
import { resolve } from 'path' import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import react from '@vitejs/plugin-react' export default defineConfig({ main: { plugins: [externalizeDepsPlugin()] }, preload: { plugins: [externalizeDepsPlugin()] }, renderer: { resolve: { alias: { '@renderer': resolve('src/renderer/src') } }, plugins: [react()], build: { rollupOptions: { input: { main: resolve(__dirname, 'src/renderer/index.html'), video: resolve(__dirname, 'src/renderer/video.html') } } } }, })
确认生产环境路径正确性
打包后渲染资源会输出到out/renderer目录,主进程中__dirname在生产环境对应out/main目录,原代码中的join(__dirname, '../renderer/video.html')路径是正确的,无需修改。验证打包结果
执行npm run build后,检查out/renderer目录是否同时存在index.html和video.html,若存在则配置生效。
额外说明
- 开发环境下Electron-Vite的dev server会自动处理所有静态文件,因此
video.html能正常访问,但生产环境必须显式配置多页面入口才能让Vite打包该文件。 - 保持
webSecurity: true即可,路径问题解决后不会出现资源加载或跨域问题。
内容的提问来源于stack exchange,提问作者Seppo
相关产品推荐
相关产品推荐

