Electron - 工程开发Tips

1. 概述

本文介绍Electron项目开发的一些经验和坑,主要是基于Electron的IM项目。

2. 开发基础

2.1. Vue和React脚手架

  • vue-cli-plugin-electron-builder good
    https://github.com/nklayman/vue-cli-plugin-electron-builder

  • electron-vite-react-starter good
    https://github.com/Harhao/electron-vite-react-starter

2.2. Electron Store

  • config with encryptionKey
    https://github.com/sindresorhus/electron-store

2.3. Electron多窗口 + 托盘 + 截图

https://www.cnblogs.com/xiaoyan2017/p/14403820.html
https://github.com/nashaofu/dingtalk
https://www.cnblogs.com/xiaoyan2017/p/14454624.html
https://www.cnblogs.com/xiaoyan2017

2.4. Default Path

  • 自动升级的安装包下载路径
    C:\Users\Administrator\AppData\Local\foxchat-updater

  • electron-log的默认路径
    C:\Users\Administrator\AppData\Roaming\FoxChat\logs

3. Electron samples

3.1. fsharechat

商业项目,基于Vue的UI,看着不错
还有webrtc功能,做音视频时可以参考
https://github.com/fsharechat/vue-chat
https://github.com/han960619/Vue-chat
https://han960619.github.io/Vue-chat/#/chat

  • 登录功能
    https://github.com/fsharechat/vue-chat/blob/master/src/page/login/login.vue

  • 侧边栏sidebar
    https://github.com/fsharechat/vue-chat/blob/master/src/components/mycard/mycard.vue

  • 会话列表
    https://github.com/fsharechat/vue-chat/blob/master/src/components/chatlist/chatlist.vue

  • 聊天窗口,包含单聊、群聊、输入框
    https://github.com/fsharechat/vue-chat/blob/master/src/components/message/message.vue
    https://github.com/fsharechat/vue-chat/blob/master/src/components/text/text.vue

  • 好友页面
    https://github.com/fsharechat/vue-chat/blob/master/src/page/friend/friend.vue

  • 登录页面
    https://github.com/fsharechat/vue-chat/blob/master/src/page/login/login.vue

3.2. aermin

react的im,不错的项目,可以重点学习,有正在运行的实例
没有用第三方组件库,而是react原生的组件
https://github.com/aermin/ghChat
https://im.aermin.top

  • 单聊框
    https://github.com/aermin/ghChat/blob/7be727183a/src/components/PrivateChat/index.js

  • 群聊框
    https://github.com/aermin/ghChat/blob/7be727183a/src/components/GroupChat/index.js

3.3. chat-react

可以跑起来,前端react,后端go,数据库用mysql
UI一般,没有太多参考的价值
后端用Go写的,有空可以学习下

go run .
yarn start

https://gitee.com/ltly/chat-react
https://gitee.com/ltly/chat-online

4. Feature

开发IM客户端时,实现Feature过程的思考

4.1. emoji feature

emoji-mart

https://github.com/missive/emoji-mart

优点:表情很丰富,功能也很全,支持自定义emoji

缺点:

  • 单个emoji的展示,需要自己完成
  • 加载很多emoji时候,很卡,尤其是第一次
  • emoji不会动,不美观

third party: rich editor

https://ant.design/docs/react/recommendation
https://github.com/zenoamaro/react-quill
https://github.com/margox/braft-editor
功能都挺全,用在IM里面有点重(不用支持表情和文本即可,不用加粗、斜体、字号等),所以暂且舍弃

react-contenteditable

https://github.com/lovasoa/react-contenteditable
https://codesandbox.io/s/l91xvkox9l
符合IM当前需求,可以自定义支持的tag,很赞~
渲染前,通知sanitize-html消一下毒
https://github.com/apostrophecms/sanitize-html
渲染时候,通过dangerouslySetInnerHTML渲染即可
https://www.pluralsight.com/guides/how-to-render-html-in-state-string

4.2. catch chat input focus

方法1,removeAllRanges之后,lastRange又回到了开始位置0,怀疑是引用导致,在失去焦点时候,改成document.getSelection().getRangeAt(0).cloneRange()也不行

if (this.state.lastRange) {
  selection.removeAllRanges()
  selection.addRange(this.state.lastRange)
}

但是,下面这个例子是work的。很奇怪,有时间再深入研究
https://segmentfault.com/a/1190000005869372

方法2,步骤和优缺点如下

  • 失去焦点onBlur时候,记录range.endOffset
const lr = document.getSelection().getRangeAt(0)
lastRangeEndOffset = lr.endOffset // number
  • 获取到焦点时候,设置光标位置
const obj = document.getElementById("inputbox")
selection?.collapse(obj, lastRangeEndOffset)

优缺点

  • 优点:记录input失去焦点是光标位置,下次获取焦点,能够成功插入,在两个场景上体验较好:input没有获取焦点时,点击表情面板并输入表情;input没有获取焦点时,键盘输入可见字符时。

  • 缺点:当text和emoji混合时,记录的光标位置,可能是基于Text的,也可能是基于整个nodeList的,所以,恢复焦点时,设置光标位置,就不能简单的如上操作。会导致光标位置不正确,或者js报错(当lastRangeEndOffset > nodeList.length时)

方法3,input非焦点时,点击输入emoji或者键盘输入可见字符时,直接插入到最后即可

var selection = document.getSelection()
const obj = document.getElementById("inputbox")
selection?.collapse(obj, obj.childNodes.length)

飞书的做法:只支持emoji输入到既定光标上。当键盘输入字符时,默认插入到最后,而且当输入中文时,第一个字母会丢失(原因是用于获取focus,上述3个方法同样存在)。

综合对比,采用方法3,逻辑清晰,体验还好。

5. 坑

5.1. change BrowserRouter to HashRouter

React assets图片,在build之后,经过react-route之后,会报错404,解决办法:

  • import
import { Image } from 'antd';
import imgUrl from '../../assets/images/coding.png'



  • change BrowserRouter to HashRouter
    https://github.com/csepulv/electron-with-create-react-app/issues/19#issuecomment-498101077

5.2. ipcMain.handle

同一个channel只能被ipcMain.handle只能注册一次,第二次注册会被block住(莫名其妙,还不错报个错),如果想第二次注册成功,需要先调用ipcMain.removeHandler
https://www.electronjs.org/docs/api/ipc-main#ipcmainremovehandlerchannel

5.3. auto-updater取错本地版本号

electron-updater自身的bug,会去取Electron的版本
解决方案: 修改electron-updater中appUpdater.js中isUpdateAvailable函数代码

const pkg=require('../../../package.json');
const isLatestVersionNewer = (0, _semver().gt)(latestVersion, pkg.version);

5.4. Proxy

Linux的proxy,只支持10.0.0.0/8,不支持10.*
Windows下,通过cygwin64,也应该如下配置no_proxy,否则通过yarn electron-builder --publish always,也会发布失败。例如:

$ export no_proxy=localhost,10.0.0.0/8,127.0.0.1,::1

你可能感兴趣的:(Electron - 工程开发Tips)