Electron分发构建中启动屏加载失败(白屏问题)
Electron启动屏构建后白屏问题解决及优化方案
问题核心诊断
开发模式下启动屏正常是因为直接读取本地src/renderer/splashscreen.html文件,但构建后:
- electron-vite默认未将
splashscreen.html纳入renderer构建输出目录 - electron-builder配置排除了src目录,且未正确包含构建后的启动屏文件
- main进程中
loadFile('src/renderer/splashscreen.html')的路径在打包后完全无效,导致加载失败白屏
分步解决步骤
1. 调整electron-vite配置,纳入启动屏文件
修改项目根目录的electron.vite.config.ts,将splashscreen.html作为renderer的额外入口,确保被构建输出:
import { defineConfig } from 'electron-vite' import { resolve } from 'path' export default defineConfig({ renderer: { build: { rollupOptions: { input: { main: resolve(__dirname, 'src/renderer/index.html'), splash: resolve(__dirname, 'src/renderer/splashscreen.html') } } } } })
执行yarn build后,out/renderer目录下会同时生成index.html和splashscreen.html。
2. 修正electron-builder.yml配置
确保构建后的文件被完整打包进应用,去掉对splashscreen.html的排除规则,保留对src目录的排除(避免源码泄漏):
# electron-builder.yml appId: com.your-app.id productName: YourApp files: - '!src/**/*' - 'out/**/*' # 包含所有构建输出文件 directories: output: dist
3. 修正main进程的启动屏加载路径
打包后main进程的代码位于out/main目录,需根据环境动态切换加载路径:
// src/main/index.ts import { app, BrowserWindow } from 'electron' import { join } from 'path' function createLoadingWindow() { const loadingWindow = new BrowserWindow({ frame: false, transparent: true, width: 400, height: 300, resizable: false, show: false // 先隐藏,加载完成后再显示 }) // 根据打包状态切换加载方式 if (app.isPackaged) { // 打包后路径:从main目录向上一级到renderer目录 loadingWindow.loadFile(join(__dirname, '../renderer/splashscreen.html')) } else { // 开发模式下直接访问Vite dev server的启动屏页面 const devUrl = `http://${process.env.VITE_DEV_SERVER_HOST || 'localhost'}:${process.env.VITE_DEV_SERVER_PORT || '5173'}/splashscreen.html` loadingWindow.loadURL(devUrl) } // 页面加载完成后显示窗口 loadingWindow.webContents.on('did-finish-load', () => { loadingWindow.show() }) return loadingWindow }
4. 验证构建结果
执行yarn build:mac后,打开dist/mac/YourApp.app/Contents/Resources/app.asar(可使用asar extract命令解压查看),确认renderer目录下存在splashscreen.html。
更优实现方案
1. 整合启动屏到主页面
无需单独创建BrowserWindow,在主窗口的index.html中嵌入启动屏组件,通过CSS控制显示/隐藏:
<!-- src/renderer/index.html --> <div id="splash-screen" style="position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: #fff;"> <div>加载中...</div> </div> <div id="main-content" style="display: none;"> <!-- 主内容 --> </div>
在主页面的JS中,等资源加载完成后隐藏启动屏:
window.addEventListener('DOMContentLoaded', () => { // 模拟资源加载 setTimeout(() => { document.getElementById('splash-screen').style.display = 'none' document.getElementById('main-content').style.display = 'block' }, 2000) })
这种方式减少了窗口创建的开销,也避免了打包配置的复杂问题。
2. 预加载启动屏资源
在main进程启动时,提前读取启动屏文件内容,通过loadURL直接加载:
import { readFileSync } from 'fs' import { join } from 'path' // 在createLoadingWindow中 let splashContent: string if (app.isPackaged) { splashContent = readFileSync(join(__dirname, '../renderer/splashscreen.html'), 'utf-8') } else { splashContent = readFileSync(join(__dirname, '../../src/renderer/splashscreen.html'), 'utf-8') } loadingWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(splashContent)}`)
内容的提问来源于stack exchange,提问作者andvch
相关产品推荐
相关产品推荐

