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深度總結思惟導圖,總結的很是棒,許多細節使筆者受益良多。出處

相關文章
相關標籤/搜索