本文主要講以下幾點
- 簡單介紹electron
- electron的程式與渲染層通訊
- electron的打包配置
- electron的自動更新
- electron如何整合sqlite3
- electron的資料分享
- electron在內網開發的一點點建議
- electron主程式的生命週期
快速開始一個electron與簡介
electron是什麼
開啟官網第一眼就是使用 JavaScript, HTML 和 CSS 構建跨平臺的桌面應用
,更加通俗一點就是一個桌面瀏覽器,實際上這樣理解也是對的。因為electron就是通過javaScript使chromium來展示web頁面
我為啥用它
- 前端可用製作跨平臺應用
- 生態圈好
- 由github開發維護
- electron(70+k)比nw.js (35+k)Star多兩倍
- electron產品我使用過表現優秀
- Vscode
- Atom
- gitHub桌面端
- ...
如何快速上手electron
我認為以下是快速開始的最好辦法
- 一定要多讀官方文件,可以減少大部分時間
- 官方提供的快速開始模板
- 官方提供快速熟悉的API的模板
直接使用electron官方提供的例子
// 看這個的原始碼,很簡單可以快速上手
# 克隆這倉庫
$ git clone https://github.com/electron/electron-quick-start
# 進入倉庫
$ cd electron-quick-start
# 安裝依賴庫
$ npm install
# 執行應用
$ npm start
複製程式碼
如果想了解這個electron的API可以克隆這個庫並執行
git clone https://github.com/electron/electron-api-demos
cd electron-api-demos
npm install
npm start
複製程式碼
如何除錯electron
渲染程式除錯(web頁面)
渲染器程式這chrome瀏覽器一樣,BrowserWindow建立視窗後新增視窗例項.webContents.open
主程式Electron除錯 使用vsCode中的debug,注意除錯路徑,如果需要增加變數環境依照配置增加即可
electron中主程式的生命週期以及常用事件和渲染層
主要聊electron中主程式的生命週期,渲染器的部分生命週期,一般只介紹通用都存在的,如果只有某個系統有的api就不寫在這裡了,大家可以自行查閱
主程式中的生命週期
正常流程會觸發的生命週期
will-finish-launching
:當應用程式完成基礎的啟動的時候被觸發web-contents-created
:webContents被建立完成browser-window-created
:BrowserWindow被建立完成ready
:當 Electron 完成初始化時被觸發remote-require
: 引入remote時被呼叫before-quit
: 在應用程式開始關閉視窗之前觸發will-quit
:當所有視窗都已關閉並且應用程式將退出時發出quit
: 在應用程式退出時發出window-all-closed
:當所有的視窗都被關閉時觸發
這裡要注意如果是程式殺死退出的所有都不觸發,如果是
cmd+Q
或者開發者使用app.quit()
退出的window-all-closed
是不會被觸發的,基本操作一般在ready中處理
程式相關
gpu-process-crashed
: 當 gpu 程式崩潰或被殺時觸發。
其他
browser-window-focus
: 在 browserWindow 獲得焦點時發出browser-window-blur
:在 browserWindow 失去焦點時發出
渲染程式--(瀏覽器)-BrowserWindow
ready-to-show
:當頁面已經渲染完成(但是還沒有顯示) 並且視窗可以被顯示時觸發move
: 視窗移動resize
: 調整視窗大小後觸發close
: 在視窗要關閉的時候觸發。 它在DOM 的beforeunload 和 unload 事件之前觸發.blur
: 失去焦點,同appfocus
: 獲得焦點,同appmaximize
:視窗最大化時觸發unmaximize
: 當視窗最大化退出狀態觸發minimize
: 視窗最小化時觸發restore
: 當視窗從最小化還原觸發- ...
渲染程式 BrowserWindow例項中的webContents
did-finish-load
:導航完成時觸發,即選項卡的旋轉器將停止旋轉,並指派onload事件後did-finish-load
: 這個事件類似於 did-finish-load, 不過是在載入失敗或取消後觸發dom-ready
: 一個框架中的文字載入完成後觸發該事件crashed
: 當渲染程式崩潰或被結束時觸發unresponsive
: 頁面未響應觸發devtools-opened
: 當開發者工具被開啟時,觸發該事件。devtools-closed
: 當開發者工具被關閉時,觸發該事件。- ...
electron的程式與渲染層通訊
- 主程式和渲染器程式
- 主程式和渲染器程式的區別
chrome瀏覽器由於每個標籤頁都是一個程式,而electron所執行的程式稱為主程式並且只有一個,主程式要操控瀏覽器的每個標籤的網頁稱為渲染器程式,如何通訊呢?
主程式和渲染器程式
程式
程式是正在執行的程式的例項(狹義定義)
electron中的主程式
Electron 執行 package.json 的 main 指令碼的程式被稱為主程式。 在主程式中執行的指令碼通過建立web頁面來展示使用者介面。 一個 Electron 應用總是有且只有一個主程式。
electron中的渲染器程式
由於 Electron 使用了 Chromium 來展示 web 頁面,所以 Chromium 的多程式架構也被使用到。 每個 Electron 中的 web 頁面執行在它自己的渲染程式中。
渲染器程式與主程式之間的區別
- 主程式是從開始執行一直存在,渲染器程式通過BrowserWindow來建立例項,例項銷燬則渲染程式銷燬
主程式使用 BrowserWindow 例項建立頁面。 每個 BrowserWindow 例項都在自己的渲染程式裡執行頁面。 當一個 BrowserWindow 例項被銷燬後,相應的渲染程式也會被終止。
- 主程式管理所有渲染程式,渲染程式是獨立且自我管理(web頁面)
主程式管理所有的web頁面和它們對應的渲染程式。 每個渲染程式都是獨立的,它只關心它所執行的 web 頁面。
- 主程式中可以呼叫底層所有的GUI的API,渲染程式則因為安全問題不能隨意呼叫。如果要呼叫則需要通訊讓主程式來呼叫。
在頁面中呼叫與 GUI 相關的原生 API 是不被允許的,因為在 web 頁面裡操作原生的 GUI 資源是非常危險的,而且容易造成資源洩露。 如果你想在 web 頁面裡使用 GUI 操作,其對應的渲染程式必須與主程式進行通訊,請求主程式進行相關的 GUI 操作。
主程式與渲染器程式如何通訊
主程式與渲染器程式通過ipcMain與ipcRenderer來通訊
主程式向渲染器程式通訊
這個方式主要是主程式中使用ipcMain使用on監聽,監聽獲取後通過event.sender
(相當於webContent)send
來傳送一個事件,渲染程式中使用ipcRenderer通過on來接收,如果是同步可以通過evnet.returnValue
來返回主程式的結果程式碼如下:
渲染器程式向主程式通訊
渲染器程式主要通過ipcRenderer這個模組中的send來傳送,該方法中可以同步與非同步傳送訊息,接收訊息使用on來接收
electron的打包
常用方式:
- electron-builder(本人主要用這個)
- electron-pakager
- electron-forge
electron-builder
electron-builder 是一個完整的解決方案,並且自帶自動更新策略
electron-builder打包在package的script配置好
打包常用引數:
"build": {
"appId": "your.id", // appid
"productName": "程式名稱", // 程式名稱
"files": [ // 打包需要的不過濾的檔案
"build/**/*",
"main.js",
"node_modules/**/*"
],
"directories": {
"output": "./dist-out", // 打包輸出的目錄
"app": "./", // package所在路徑
"buildResources": "assets"
},
"nsis": {
"oneClick": false, // 是否需要點選安裝,自動更新需要關掉
"allowToChangeInstallationDirectory": true, //是否能夠選擇安裝路徑
"perMachine": true // 是否需要輔助安裝頁面
},
"win": {
"target": [
{
"target": "nsis", // 輸出目錄的方式
"arch": [ // 輸出的配置ia32或者x64/x86
"x64"
]
}
],
"publish": [ // 自動更新的配置
{
"provider": "generic", // 自己配置更新的伺服器要選generic
"url": "http://127.0.0.1:8080/updata/" //更新配置的路徑
}
]
}
}
複製程式碼
在package.json中增加的快速啟動項
"scripts": {
"pack": "electron-builder --dir",
"dist": "electron-builder"
}
複製程式碼
啟動打包
通常需要注意的點
- 注意路徑,由於打包後的路徑會有問題最好使用
path.join()
來處理一下。 - 碰到
The process cannot access the file because it is being used by another process.
這個問題多數是vscode佔用了關掉重開就好了
如果配合create-react-app建立出來的應用
- 可以先讓react的程式進行打包成靜態檔案,在把靜態檔案打包到electron應用中
- 如果electron-builder總是報類似
electron.js
找不到的警告,並且在上面提示讓你去看網頁中的方法,可以通過electron-builder提示的網址來修改,這實際是一個教程需要科學上網。
electron-builder的自動更新
如果在API中看到autoUpdater這個API,希望在看到這個API之前先參考官方的自動更新這樣會讓你少點坑,因為electron-builder的自動更新機制和electron提供有些不一樣,electron-builder官網也有說明,否則就會一直報error了
這個更新實際上是對比例兩個版本之間的版本號,如果當前版本小於,伺服器版本的話就會進行下載更新
更新機制
在資料裡有一篇專門講更新機制的,很好。這裡簡單總結。
autoUpader生命週期
error
: 如果任意一個環節有問題就會走到這步checking-for-update
:當開始檢查更新的時候觸發。update-available
: 發現更新update-not-available
:當沒有可用更新的時候觸發.update-downloaded
: 在更新下載完成的時候觸發。before-quit-for-update
: 此事件是在使用者呼叫quitAndInstall()之後發出的。
更新要注意的點:
- electron-builder中的autoUplader需要使用
electron-updater
這個模組,非原生模組 - package.json中的publish中的url與更新的地址要一致(注意埠),否則會報
net::ERR_CONNECTION_REFUSED
- 如果是未打包也想跑一邊
autoUpdater
的流程需要一個dev-app-update.yml
的檔案放在與main.js
同一層級的地方,類似win-ia32-unpacked/resource/app-update.yml
這樣的檔案,直接複製改名就能使用 - 如果更新完成後在package中配置了自動安裝的選項,在關閉應用就能直接安裝,如果想自己控制馬上安裝需要加
autoUpdater.quitAndInstall()
- 如果初次啟動應用在終端輸出了你想要的結果,在渲染選只輸出來了一部分,或者沒有輸出,如果不是報錯的話,不妨監聽一下該渲染程式的
did-finish-load
這個宣告週期,在這裡面做處理,根據場景可以使用once
來監聽 - 需要一個靜態網站伺服器在你需要的資料夾使用
http-server -o
,如果沒有就全域性安裝一個npm i http-server -g
,在package中需要配置publish
中的"provider": "generic"
- 碰到
spawn **/*.exe ENOENT
這類的可能是你在開發環境執行了一個未安裝的應用,並且使用了autoUpdater.quitAndInstall()
就會報錯,如果是安裝好了就不會報這個錯
//electron-quick-start
//main.js 主程式中
// 可以沒有這個
const { autoUpdater } = require('electron-updater')
// ================= start 非必須 ===============
const log = require('electron-log');
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
// ================ end 非必須 ==================
// 封裝
function sendStatusToWindow(text) {
log.info(text);
mainWindow.webContents.send('message', text);
}
/**
* 自動更新
*/
function checkUpdata() {
autoUpdater.setFeedURL('http://127.0.0.1:8080/updata/')
// autoUpdater.on('error', (error) => {
// sendStatusToWindow( `[error]:${error}`)
// })
autoUpdater.on('checking-for-update', () => {
sendStatusToWindow('Checking for update...');
// mainWindow.webContents.send('downlaod')
})
autoUpdater.on('update-available', (info) => {
sendStatusToWindow('Update available.');
})
autoUpdater.on('update-not-available', (info) => {
sendStatusToWindow('Update not available.');
})
autoUpdater.on('error', (err) => {
sendStatusToWindow('Error in auto-updater. ' + err);
})
autoUpdater.on('download-progress', (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
sendStatusToWindow(log_message);
mainWindow.webContents.send('downloadExe', progressObj.percent)
})
autoUpdater.on('update-downloaded', (info) => {
mainWindow.webContents.send('downloaded')
sendStatusToWindow('Update downloaded');
// autoUpdater.quitAndInstall();
});
複製程式碼
electron中新增sqlite3
需要的環境
如果是windows環境需要準備 vs2015 與python2.7的環境
- python2.7.x 網上下載安裝即可
- vs2015 以下方式可選其一
- 工具包
npm install --vs2015 -g windows-build-tools
(推薦) - 安裝visual studio 中安裝vs2015工具包(超久)
- 工具包
程式中可新增的本地資料庫,最多使用的兩款
- sqlite3(關係型)
- neDB(非關係型)
為自己的資料加上本地資料庫sqlite3
sqlite3【gitHub】
為程式新增sqlite3npm i sqlite3
或者yarn add sqlite3
如何使用?
// 官網例子
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:'); // 這裡是把資料存入記憶體
db.serialize(function() {
var db = new sqlite3.Database()
db.run("CREATE TABLE lorem (info TEXT)");
var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
stmt.run("Ipsum " + i);
}
stmt.finalize();
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
console.log(row.id + ": " + row.info);
});
});
db.close();
複製程式碼
sqilte3在安裝的時候自動生成sqlite所需要的檔案包,這個二進位制檔案需要使用node-pre-gyp
或者是node-gyp
這也就是為什麼需要安裝環境的原因,在這一步鬼知道當時報了多少東西,尤其是還要把這玩意弄進內網。
比如說:
- 開始執行的時候就報
Error: Cannot find module 'E:\electronjs\electron-quick-start\node_modules\sqlite3\lib\binding\electron-v4.0-win32-x64\node_sqlite3.node'
類似這樣的東西,實際上確實沒有這個東西,怎麼解決呢?- 使用
node-gyp
這個模組直接重新編譯一個版本正確的
- 使用
node-gyp rebuild
--target=4.0.4 --arch=x64
--target_platform=win32 --dist-url=https://atom.io/download/electron/
--module_name=node_sqlite3 --module_path=../lib/binding/electron-v4.0-win32-x64
// 使用到的模組解析
// target => electron的版本號一定要一直
// target_platform => 需要打包的平臺ia32/x64等
// dist-url => 這個是需要下載相關內容的地址
// module_name => 需要打包的模組名稱
// module_path => 打包輸出的地方
複製程式碼
如果覺得麻煩可以試試npm i electron-rebuild -D
然後在使用./node_modules/.bin/electron-rebuild
重新編譯一遍,有時候可能是快取問題,把快取清除npm cache clear -f
清除一下,還有就是npm i
重新安裝一下,因為環境的問題會跳出各種問題,可以多多嘗試這些方法
was compiled against a different Node.js version using
NODE_MODULE_VERSION 64. This version of Node.js requires
NODE_MODULE_VERSION 69. Please try re-compiling or re-installing
複製程式碼
如讓你選擇node編譯版本的github【issues】====>也有可能是編譯問題,利用electron-rebuild 重新編譯一遍或者把sqlite3降級
需要注意的
- 打包的時候如果報
error MSB4019: 未找到匯入的專案Microsoft.WebApplication.targets
重新安裝一下vs2015工具包,或者以前安裝的有問題重新安裝(我就碰到了) - 用node-gyp編譯sqlite3打包需要
binding.gyp
這個python檔案以及其他配置所以直接進入node_modules\sqlite3
這個檔案執行 node-gyp的操作 - 打包的時候要注意在渲染程式中使用sqlite3在打包的時候會出現打包問題,解決可以選在在主程式操作本地資料庫
- 打包之後使用DB會出現一個問題,在當前目錄怎麼都生成不了DB,在網上查了要麼就通過手動授權為管理員開啟,要麼手動管理員開啟,這根本就不能行,後來參考
electron-vue
發現可以使用app.getPath('userData')
這個方法進行獲取app可快取地址,然後使用path.join
合併一下路徑就解決了無法生成DB檔案的問題,事實上indexDB,locaStore這個兩個的儲存檔案也在這個目錄下
其他模組
globalShortcut
: 註冊全域性快捷鍵Tray
: 托盤Menu
:選單事件
內網開發需要注意
內網開發真的很煩。。 首先需要環境,然後就是需要下載的包,其次就是需要編譯後的各種檔案如sqlite3編譯後的檔案等如果在內網開發electron就需要把這些需要的包全都複製到對應位置
大部分需要配置的檔案都在C:\Users\xxx
xxx代表你所在的資料夾,
部分下載快取檔案在C:\Users\xxx\AppData\Local
目錄下的electron 和 electron-builderer裡
參考的學習資料
以下文章大部分閱讀過,覺得不錯推薦給大家
electron
- electron官網-文件必啃,少踩80%的坑
- Electron,從玩玩具的心態開始,到打造出一款越來越優秀的桌面客戶端產品 —— 一份不是「Hello Word」的吊胃口的Quick Start
- 【譯】Electron 的本質
- 【科學上網】從React到準備生產的Electron應用程式
- 蘇南大叔的electron集合
- [electron]終極奧義 五千字教程丟給你
- Electron構建跨平臺應用Mac/Windows/Linux
- Electron 深度實踐總結
- 【科學上網】electron相關基礎
electron構建相關
- Electron 應用如何利用 create-react-app 從 0 到1
- Electron系列文章-程式目錄結構
- Webpack實戰-構建 Electron 應用
- React + Electron 搭建一個桌面應用
electron打包相關
- electron-builder官網
- 瞭解 Electron 打包
- 用 Electron 打造 Win/Mac 應用,從「程式碼」到可下載的「安裝包」,可能比你想得麻煩一點
- 打包優化
- 雙package方案
- electron-builder打包見解
electron更新
electron
- 使用 Electron 構建桌面應用
- 如何使用Electron使用JavaScript構建您的第一個桌面應用程式
- 使用Electron構建Todo應用程式-科學上網
- XCel 專案總結 - Electron 與 Vue 的效能優化【凹凸實驗室】