公司动态
Electron 打包后启动白屏无响应排查实录:Express 本地服务 + asar 资源路径的坑
## 现象开发环境好好的一打包就白屏花店进销存 ERP 是 Electron Vue3 Express SQLite 的架构开发模式 npm run dev 双开 Vite 和 Express一切正常。用 electron-builder 打成 exe 后双击启动任务管理器里进程是有的但窗口一片白点哪里都没反应。最迷惑的是主进程日志里 did-finish-load 都打出来了——页面加载完成了但渲染出来是白的。## 失败方案一关掉 webSecurity 试试第一反应是跨域毕竟渲染进程要访问本地 Express 服务。直接在 webPreferences 里把安全关了webPreferences: { webSecurity: false, nodeIntegration: true }白屏确实消失了但 F12 一开全是 SecurityError 警告。这属于拿安全换显示以后要真上架审核直接毙掉。PASS。## 失败方案二改 Vue 的 publicPath怀疑是打包后静态资源路径不对把 vite.config 的 base 改成 ./ 重新打。没用还是白。这条路走完基本可以排除纯前端资源的问题了。## 排查思考白屏到底是哪一环断了冷静下来分三层查1. 渲染进程 JS 报错了吗 ——主进程加 webContents.on(console-message) 把渲染进程日志打出来发现脚本压根没执行白屏源头就在加载阶段2. Express 服务起来了吗 ——开发模式我监听 3325 端口是写死的但打包后主进程启动 Express 是异步的 loadURL(http://localhost:3325) 执行时服务还没 listen 完 时序竞态 页面拿到的是连接被拒绝3. 资源路径对不对 ——electron-builder 默认把代码打进 app.asar express.static(path.join(__dirname, public)) 指向 asar 内部fs 根本读不出来。三个问题叠一起任何一个都能白屏。## 最终方案环境区分 随机端口 就绪后再加载思路是开发走 Vite生产走内嵌 Express用 app.isPackaged 区分同时把静态资源目录通过 extraResources 拷出 asar# electron-builder.yml extraResources: - from: dist to: webconst server express(); server.use(express.static(app.isPackaged ? path.join(process.resourcesPath, web) : path.join(__dirname, ../dist))); const port app.isPackaged ? 0 : 3325; // 生产随机端口避免冲突 server.listen(port, 127.0.0.1, () { const url http://127.0.0.1:${server.address().port}; mainWindow.loadURL(url); });关键三点- 端口随机 打包后 port: 0 让系统自动分配拿到真实端口再 loadURL彻底解决时序竞态- 资源放 resourcesPath 用 extraResources 把 web 目录拷出来不塞进 asarfs 才能正常读- 127.0.0.1 而非 localhost 避免某些机器 IPv6 把 localhost 解析成 ::1 服务只监听 IPv4 就白屏。配合 CSP 允许 connect-src http://127.0.0.1:* 白屏问题彻底解决。## 工程取舍理论最优 vs 小团队现实这个坑有两个理论最优方案我们都没上1. 用 protocol.handle 注册自定义协议app://。 Electron 官方推荐做法把本地资源挂到自定义协议上绕开 file:// 的限制也不用起本地服务。但实现要写协议拦截、处理 MIME调试还麻烦。团队两个人、工期紧放弃。内嵌 Express 虽然土但和现有 Web 版代码完全复用一套后端两端跑。2. 数据层上 ORM。 想优雅可以上 sequelize 管 SQLite但我们已有几十个手写 SQL 的 Collection 数据层全量迁移成本太高选择保留。这就是小团队 ERP 的现实先跑起来再谈重构。最终选择 内嵌 Express 随机端口 extraResources。丑是丑但改动小、可读性好Web 端和桌面端共用同一套后端代码后续维护成本反而低。顺带一提磁场花艺这套花店进销存 ERP 从采购、库存、销售到财务桌面端和网页端共用一套 Express 后端整个开发过程用 Trae 辅助白屏这类问题它会引导我去查 electron-builder 的 asar 配置和主进程启动时序省了不少翻文档的功夫。