electron+go 实现跨平台是否可行?

2020-05-05 11:22:50 +08:00
 teawithlife

五一期间花时间学习了一下 electron,基本算是入门吧

学习的目的是为了解决跨平台桌面应用的开发问题,虽然也算熟悉 Qt,但是相对目前日新月异的新技术来说,有点太“经典”了

所以考虑用 electron 来做跨平台桌面应用开发,我的想法是拿 electron 做前端,再用 golang 写个后端,负责一些比较底层,或者对运行效率要求比较高,抑或是有保密需求的工作。electron 和 golang 的跨平台都非常容易实现,这样就可以比较完美的实现这个需求。

一开始我把后端放在服务器上,但是就要求使用者必须要联网才能使用,这个有些麻烦。后来找到 child_process, 于是可以把可执行程序直接放在程序包中,然后 spawn 出后端程序,再进行进程间通讯即可

目前有几个问题想请教一下各位大佬:

  1. 有大佬尝试过这种组合吗?有没有什么坑?为什么没怎么看到有人这么搞?

  2. 从 electron 启动后端程序,可以放在 app.ready 事件中,但是程序退出时需要自动关闭后端,放在哪个事件比较合适?因为我看到 before-quit, will-quit, quit 这三个事件,都标注了

    Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.

    而 window-all-closed 事件,又说

    If the user pressed Cmd + Q, or the developer called app.quit(), Electron will first try to close all the windows and then emit the will-quit event, and in this case the window-all-closed event would not be emitted.

    那么到底放在哪个事件里更合适呢?

  3. 进程间通讯我用 HTTP 接口,一个原因是开发方便,另一个原因是做成 web 也可以通用,但是这里存在一个后端绑定哪个端口的问题,我想了两个方案:

    • 方案一是 electron 先找一个可用端口,然后通过命令行参数的方法传给后端,缺点在于没有找到一个比较好的查找可用端口的方法(看了几个库,都是通过尝试 listen 的方法,这种方法存在一个小概率竞争的可能性)
    • 方案二是后端随机绑定一个端口,然后通过 ipc 的方法,然后把端口号传给前端,这个方案就是担心有点不通用

    不知道还有没有更好的方法?

9704 次点击
所在节点    问与答
34 条回复
HuHui
2020-05-05 11:53:00 +08:00
可以再看看 therecipe/qt
teawithlife
2020-05-05 12:09:08 +08:00
@HuHui #1 这个用到了 cgo 吧? cgo 的交叉编译有些麻烦
SingeeKing
2020-05-05 12:29:31 +08:00
我个人不喜欢 electron 的两大原因是体积大和启动慢,这个似乎优化的点在执行效率
Jirajine
2020-05-05 12:33:05 +08:00
有一个 go 的 electron 绑定 https://github.com/asticode/go-astilectron
但看起来不太成熟。
至于你说的起一个后台服务然后 IPC 交互我一个自己用的小玩意就是这么搞的,除了有点套娃没发现什么坑,也没考虑那么多直接 quit 完事。端口直接随机一个然后参数传过去。
这样做好处就是天然支持后端远程运行,不然还不如传统的 native 扩展方便,或者 wasm 也不错。
pkwenda
2020-05-05 12:39:35 +08:00
刚想发就被楼上发了,electron 很重的 。
teawithlife
2020-05-05 12:41:40 +08:00
@SingeeKing #3 体积大显得有份量,有工作量(:P ),启动慢这个确实有点不好,不过现在按现在的平均硬件水平,已经勉强可以接受了。主要优化的点在于 js 我不熟(手动狗头)
teawithlife
2020-05-05 12:49:48 +08:00
@Jirajine #4 感谢推荐,这个库看起来还不错,我好好看看
你随机一个端口,得先 listen 一下,确定端口没被占用,然后才能传给后端吧?我刚才又想了一个方案,前端可以自己 listen 一个端口 A,然后作为参数传给后端,后端随机 listen 一个端口 B,然后通过端口 A 告知前端。这样虽然有点绕,但是可靠性高,而且确保跨平台
wasm 还是再等等吧,目前还不算成熟
SingeeKing
2020-05-05 12:51:49 +08:00
@teawithlife #6 这不是简单的「有份量」「勉强可以接受」,electron 大的问题在于无论再小的应用都打包了一个环境进去,而一般个人电脑启动最快也要 1-2 秒,这些在一起就真的对 electron 难以有好感
murmur
2020-05-05 13:02:49 +08:00
electron 目前看到比较成功的应用就是 vscode 了,其余的都不是严格的 electron,尤其是国产那堆软件,你看着是 chrome 套壳,背后辣么一大堆 dll 都不知道干啥的
jason94
2020-05-05 13:29:15 +08:00
1. 之前看到这篇 https://wiredcraft.com/blog/high-security-electron-js-application/,也想这么搞,后来感觉有点麻烦,主要就是不好维护。保密这块可以考虑 js 源码 转字节码(目前在几十万用户运行没问题)
2. before-quit 或 will-quit 。如果窗口关闭之前不做操作的话,可以丢 before-quit 里
3. 方案一可以用这个库 https://www.npmjs.com/package/portfinder
ysc3839
2020-05-05 13:42:00 +08:00
不然考虑 Golang + Cef ?
https://github.com/CzarekTomczak/cef2go
teawithlife
2020-05-05 13:51:47 +08:00
@SingeeKing #8 这个话题记得之前 V2 也有几个主题讨论过,我部分赞同你的观点,对于一个有追求的程序员来说,体积大执行慢确实难以忍受,但同时我认为这是为了实现跨平台所要付出的代价,其实 Qt,golang 都是这么一个套路,把整个 runtime 都打包了(当然他们没 electron 那么臃肿)。所以,算是有舍有得吧,就看你以及你的最终用户看重啥了
teawithlife
2020-05-05 14:03:54 +08:00
@jason94 #10 保密是其中一个原因吧,主要还是我作为 crud boy,对前端只停留在 ctrl+c/v 程序员的程度,所以需要把大部分逻辑工作放到后端来实现
你说的 portfinder 库我看过源码,就是我说的遍历尝试 listen 的方法,这种方法存在一个极小概率的 race condition,可能前端检查的时候,这个端口是可用的,但是等到后端调用时,这个端口已经被其他进程抢先占用了(虽然概率极低,但这确实是可预见的风险)
teawithlife
2020-05-05 14:09:04 +08:00
@ysc3839 #11 这个库的 commit 记录,从 2014 年之后的记录,都是在改 README 了,不敢用。。。
Jirajine
2020-05-05 14:10:24 +08:00
@teawithlife 被占了启动服务会绑定失败,js 处理下错误重新随机一个再次启动,这个几率本身也很小,或者用楼上提到的库。
wasm 毕竟是未来,高性能扩展不用再包装一堆丑陋的 C 接口了。
teawithlife
2020-05-05 14:24:10 +08:00
@Jirajine #15 对哦,启动不起来换个端口再来一遍就行了,我咋把这个办法给忘了
optional
2020-05-05 14:39:05 +08:00
wasm 不二选择啊。
kuyuzhiqi
2020-05-05 19:03:28 +08:00
可以的,不难,不同的平台运行时把 go 的运行环境带上,electron 那边启动 go 的服务就行
teawithlife
2020-05-05 22:26:38 +08:00
从下午到晚上都在研究打包的问题,增加一些额外的信息给需要的朋友:

1. 目前打包的工具有两个 electron-builder 和 electron-packager,用 electron-vue 建立项目时,可以选择其一作为打包工具

2. electron-builder 功能较全,配置比较麻烦,除了打包之外,可以制作各种安装包,electron-packager 比较简单易用。我测试了用 electron-packager 在 linux 平台生成 linux 和 windows 的可执行程序,如果要生成 windows 平台程序,需要先自行装 wine (据说是为了改图标),也测试了用 electron-builder 在 linux 平台生成 windows 下的可执行程序和安装程序,没有需要自己安装的工具,生成的过程会自动下载(不清楚是否需要 wine,因为已经装过了),其他的平台就没测试了(注意,为了确保下载成功,请科学上网)

3. 两个工具在打包的时候都可以设置一个 asar 参数,如果为 true,会把整个 app 打包为一个 asar 文件,这样据说可以提高 IO 效率(特别是在 windows 下),由于程序较小,没有明显感觉,但是在复制的时候有明显区别,因为不打包的话,node_modules 这个文件夹得复制半天

4. 如果启用 asar 文件,在 child_process 里面的函数,exec, fork, spawn 全部都不能用,只能用 execFile,如果确实想用,可以将需要执行的文件,从 asar 文件中复制出来

5. 我把后端程序放到了 static 文件夹中,发现打包之后,`dist/static/`文件夹虽然已经有了程序,但是文件属性从 755 变成 644 了,原因是 electron-vue 的打包脚本中,复制 static 文件夹时,用的是 copy-webpack-plugin,它这个 issue 至今未解决。我最后没办法,直接修改 build.js 文件,复制完成之后,手动执行一次`chmod +x`,把权限改回来
qwe121002
2020-05-06 02:23:01 +08:00
有人会做 h5 跳转转账的付款模式吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/668620

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX