Electron工程踩坑记录

最近公司有个新产品线,须要将应用打包成客户端,提供私有化部署。考虑到Web线上已经实现大部分需求,技术选型使用Electron。本文不是帮助读者的扫盲文,只是记录下项目工程中遇到的坑,因此阅读本文须要web和electron知识。css

应产品要求,私有化部署主要考虑windows端,mac端其次。框架选型使用electron-vue脚手架(这里也强烈推荐),该脚手架包含Vue技术栈单页应用 + electron + 打包完整流程。内置Vuex,Vue-Router,Webpack,electron-builder等。下面的大部分实践源码放在这html

1. 自定义标题栏

这应该是每个使用electron实现web客户端都会遇到的问题,使用原生的外边框,第一太丑,第二也不统一。前端

解决方案:frame + css dragvue

frame: false: 主进程中设置窗体参数。去掉默认的标题栏node

-webkit-app-region: drag: 渲染进程中设置css。对应的组件能够进行拖动了linux

mainWindow = new BrowserWindow({
    height: 350,
    width: 550,
    useContentSize: true,
    resizable: isDev, // 是否可调整大小
    alwaysOnTop: !isDev, // 应用是否始终在全部顶层之上
    transparent: true, // 透明边框
    frame: false, // 不使用默认边框
    center: true
})
复制代码
.u-header {
    position: relative;
    width: 100%;
    height: 50px;
    line-height: 50px;
    -webkit-app-region: drag; /* as window header */
}
复制代码

2. 标题栏按钮无效 -- only windows

该bug只在windows平台上显示,mac上正常。在header组件中设置为drag,致使组件里的元素都没法点击。git

解决方案:在须要点击的元素上添加no-drag。-webkit-app-region: no-drag;详细看此issuegithub

3. 自定义标题栏没法实现css hover -- only windows

当设置了为drag时,在windows上会屏蔽全部的鼠标事件,因此hover不起做用。这是一个由操做系统致使的问题,故没法修复,相关issueweb

解决方案:去掉-webkit-app-region: drag;便可。macos

若是要同时保留可拖动而且hover上有变化,在windows暂时没法实现,须要对此进行取舍或改变交互设计。

4. 打包后程序调试

electron-vue在开发环境默认启用electron-debug插件开启调试。但打包完成,交付到测试同窗手里,须要在错误的时候打开开发者工具定位问题。

解决方案:经过注册快捷键,调开web的开发者模式。

globalShortcut.register('CommandOrControl+Shift+L', () => {
    let focusWin = BrowserWindow.getFocusedWindow()
    focusWin && focusWin.toggleDevTools()
})
复制代码

5. 文本不可选择

既然做为客户端,就应该像个客户端程序,不能对展现型的文本进行用户选择。

解决方案:使用css -webkit-user-select: none;

html {
    -webkit-tap-highlight-color: transparent;
    -webkit-text-size-adjust: 100%;
    height: 100%;
    -webkit-user-select: none; /* disable user select text */
}
复制代码

6. 打包参数设置

electron应用须要进行打包,变成exe可执行文件给用户。推荐使用最新的electron-builder进行打包(electron-vue脚手架中有提供该选项)。这里对经常使用的设置进行说明

scripts: {
    /** 打包成windows系统 **/
    "build": "node .electron-vue/build.js && electron-builder --win",
    /** 打包成macos系统 **/
    "build:mac": "node .electron-vue/build.js && electron-builder --mac",
},
"build": {
    /** 最终可执行文件名称:${productName}-${version}.${ext} **/
    "productName": "sight-electron-app",
    "appId": "netease.sight.controller",
    /** 压缩形式,默认normal;store打包最快,适合测试;maximum打包体积最小,适合生产模式 **/
    "compression": "maximum",
    /** 是否将多个文件合并为tar风格的归档模式 **/
    "asar": true,
    "directories": {
      "output": "build"  /** 打包结果目标地址 **/
    },
    "files": [
      "dist/electron/**/*" /** 须要打包的文件地址 **/
    ],
    /** 不一样平台设置 **/
    "mac": {
      "icon": "build/icons/icon.icns"
    },
    "win": {
      "icon": "build/icons/icon.ico"
    },
    "linux": {
      "icon": "build/icons"
    }
}
复制代码

7. 触摸板放大缩小 -- only mac

在macOS系统中,触摸板的放大缩小手指指令,会致使electron程序内的webFrame内容也跟着放大缩小。

解决方案:在renderer进程中设置其缩放范围require('electron').webFrame.setZoomLevelLimits(1, 1)

8. web端唤起本地客户端

electron提供该API能力:app.setAsDefaultProtocolClient(protocol[, path, args])

9. 禁止多开窗口

屡次双击window 的exe文件,会开启多个窗口;mac下默认开1个,但经过命令仍是能够多开。

解决方案:判断单实例:app.makeSingleInstance(callback)

/** * 防止应用多开。bugfix:sholudQuit老是返回true,故暂时注释如下代码 * 当进程是第一个实例时,返回false。 * 若是是第二个实例时,返回true,而且执行第一个实例的回调函数 */
const shouldQuit = app.makeSingleInstance((commandLine, workingDir) => {
    if (mainWindow) {
        mainWindow.isMinimized() && mainWindow.restore()
        mainWindow.focus()
    }
})
if (shouldQuit) {
    app.quit()
}
复制代码

10. 网络状态检测

客户端常常碰见断网状况处理,当网络断开时须要给用户提示,当网络链接时继续服务。一般web状况下是采起轮询服务器方式,但这种方式比较消耗服务器性能。这里能够利用electron的node工具包public-ip进行判断。public-ip查询dns获取公网ip地址,若是能拿到值表示联网正常。原本到此能够很好的解决,但产品要求的客户端,既要提供公共部署,也须要进行无外网状况下的私有化部署

解决方案:public-ip + 轮询方式。优先进行公网IP查询,若是成立则返回网络状态良好,若是查询不到再进行服务器心跳检查。实现方式参考is-online

11. 日志监听

每一个系统的异常监控都必不可少,特别是私有化部署客户端这种模式,日志记录显得必不可少。因为electron拥有node的环境,结合window.onerror收集错误信息,前端把日志记录在本地文件。当出现问题时,用户能够直接把日志文件发给开发者,从而定位缘由。若是是网络版模式,能够经过Ajax收集错误信息。若是是程序异常崩溃,window.onerror可能无法监测的到,好在electron提供了CrashReporter收集

解决方案:推荐electron-log + CrashReporter

const log = require('electron-log')

log.transports.file.level = 'info'
log.transports.file.format = '{h}:{i}:{s}:{ms} {text}'
log.transports.file.maxSize = 5 * 1024 * 1024
log.transports.console.level = false

复制代码

12. 自动更新

该需求停留在调研,这篇文章讲的很是详细,待实践好再来续更

最后,附上@changkun的electron深度总结思惟导图,总结的很是棒,许多细节使笔者受益良多。出处

相关文章
相关标签/搜索