最近公司有個新產品線,需要將應用打包成客戶端,提供私有化部署。考慮到Web線上已經實現大部分需求,技術選型使用Electron。本文不是幫助讀者的掃盲文,只是記錄下專案工程中遇到的坑,所以閱讀本文需要web和electron知識。
應產品要求,私有化部署主要考慮windows端,mac端其次。框架選型使用electron-vue腳手架(這裡也強烈推薦),該腳手架包含Vue技術棧單頁應用 + electron + 打包完整流程。內建Vuex,Vue-Router,Webpack,electron-builder等。下面的大部分實踐原始碼放在這
1. 自定義標題欄
這應該是每一個使用electron實現web客戶端都會遇到的問題,使用原生的外邊框,第一太醜,第二也不統一。
解決方案:frame + css drag
frame: false
: 主程式中設定窗體引數。去掉預設的標題欄
-webkit-app-region: drag
: 渲染程式中設定css。對應的元件可以進行拖動了
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,導致元件裡的元素都無法點選。
解決方案:在需要點選的元素上新增no-drag。-webkit-app-region: no-drag;
詳細看此issue
3. 自定義標題欄無法實現css hover -- only windows
當設定了為drag時,在windows上會遮蔽所有的滑鼠事件,所以hover不起作用。這是一個由作業系統導致的問題,故無法修復,相關issue。
解決方案:去掉-webkit-app-region: drag;
即可。
如果要同時保留可拖動並且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深度總結思維導圖,總結的非常棒,許多細節使筆者受益良多。出處