electron / electron-builer 踩坑记

最近在做一个 web server 工具,为了方便在 MacOS 和 Windows 上使用,采用了 electron 方案。

实践中也遇到了不少小问题,在此记录下。

启动程序出现白屏等待

这个问题官网有解决方案,就是等待页面脚本执行完毕,再显示窗体。处理方法如下:

1
2
3
4
5
6
7
8
9
10
const win = new BrowserWindow({
width: 800,
height: 600,
resizable: false,
show: false // 默认不显示窗体
})
win.loadFile('www/index.html')
win.once('ready-to-show', () => {
win.show() // 页面脚本都执行完毕后,再显示
})

MacOS 关闭窗体,程序不退出

程序很简单,就一个主界面,期望关闭窗体后,自动退出程序。问题表现为 MacOS 系统关闭窗体后,程序仍然在 dock 中显示,需要手动在退出。

这个问题主要是因为 MacOS 程序默认都是 dock 驻留的,不像 Windows,默认窗体关闭后等同于程序退出。

如果程序所有窗体都关闭,程序默认退出,那需要手动加入退出方法:

1
2
3
4
// 主进程
app.on('window-all-closed', () => {
app.quit()
})

菜单配置问题导致闪退

把没用的菜单配置删除后,有的菜单栏目为空,此时闪退。问题大致情况如下:

1
2
3
4
5
6
7
8
9
{
role: 'help',
submenu: [
// {
// label: 'Learn More',
// click () {}
// }
]
}

help 栏目下没有子菜单,此时会启动闪退。所以要么没有这个栏目,要么就要有子菜单。

程序中可以选中文字

在程序中,应该不能用鼠标将里面的文字选中、复制啥的。这体验就太差了。修改方法也简单,css 根节点处理下就好:

1
2
3
#app {
user-select: none;
}

减少包体积

原本 electron 的主进程代码和页面 App 代码在同一级别目录下,这样共用 package.jsonnode_modules。但是打包时候会把 node_modules 打入程序中,页面只需要编译后的代码打包到程序中就行了,所以不调整目录结构的话,无形中 node_modules 太大了。

调整结构如下:

1
2
3
4
5
6
7
8
9
10
├── electron     electron 程序代码
├── www 页面编译后代码
├── App 页面源码,编译到 www 目录
│   ├── node_modules
│   ├── package.json
│   └── src
├── build electron-builder 资源目录
├── dist electron-builder 程序打包目录
├── node_modules electron 的依赖
└── package.json

最终输出到程序包中,只有:

1
2
3
4
5
6
[
"www/**/*",
"electron/*",
"package.json",
"node_modules"
]

目前我只能做到如此。因为 electron 没发现什么优化方法。😂

程序打包

官方推荐了三种工具打包,electron-packager electron-forge electron-builder。官网说明见此

曾经用过 electron-packager,大概是命令行打包,而且还只能打包当前系统的包。

这次换了最流行的(star最多)的 electron-builder。发现 MacOS 下可以打所有系统的包,真挺方便的。

唯独就是 linux 平台,问题稍多些。

  • linux 下的各种格式的包,程序图标我至今没成功过;
  • 二进制 包和 linux 通用的 appImage 包,没什么问题,就是 appImage 稍大一点;
  • debian 系的 deb 包,要求 package.jsonauthor 字段必须有 nameemail。否则不能打包;
  • ubuntu 的 snap 包,好像需要签名,我就没弄;
  • redHat 系的 rpm 包,没打也没测试。

针对 linux,我认为直接出 二进制 包和 linux 通用的 appImage 包就行了。基本上常见的系统都能覆盖到。

如果要针对 ubuntu / linux Mint 处理,那么出 deb 包就好了。

–END–