本文包含打包
、自動更新
、簡易API
、調試
、進程通訊
等相關知識點,內容較多,可能會引發不適,請酌情查看(手動滑稽)。javascript
electron是由Github開發,是一個用Html、css、JavaScript來構建桌面應用程序的開源庫,能夠打包爲Mac、Windows、Linux系統下的應用。css
electron是一個運行時環境,包含Node和Chromium,能夠理解成把web應用運行在node環境中html
electron主要分爲主進程和渲染進程,關係以下圖vue
electron運行package.json
中的main
字段標明腳本的進程稱爲主進程java
在主進程建立web頁面來展現用戶頁面,一個electron有且只有一個主進程node
electron使用Chromium來展現web頁面,每一個頁面運行在本身的渲染進程
中react
接下來,讓代碼來發聲,雷打不動的hello world
linux
建立文件夾,並執行npm init -y
,生成package.json
文件,下載electron
模塊並添加開發依賴webpack
mkdir electron_hello && cd electron_hello && npm init -y && npm i electron -D
複製代碼
下載速度過慢或失敗,請嘗試使用cnpm,安裝方式以下git
# 下載cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 下載electron
cnpm i electron -D
複製代碼
建立index.js,並寫入如下內容
const {app, BrowserWindow} = require('electron')
// 建立全局變量並在下面引用,避免被GC
let win
function createWindow () {
// 建立瀏覽器窗口並設置寬高
win = new BrowserWindow({ width: 800, height: 600 })
// 加載頁面
win.loadFile('./index.html')
// 打開開發者工具
win.webContents.openDevTools()
// 添加window關閉觸發事件
win.on('closed', () => {
win = null // 取消引用
})
}
// 初始化後 調用函數
app.on('ready', createWindow)
// 當所有窗口關閉時退出。
app.on('window-all-closed', () => {
// 在 macOS 上,除非用戶用 Cmd + Q 肯定地退出,
// 不然絕大部分應用及其菜單欄會保持激活。
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// 在macOS上,當單擊dock圖標而且沒有其餘窗口打開時,
// 一般在應用程序中從新建立一個窗口。
if (win === null) {
createWindow()
}
})
複製代碼
建立index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1 id="h1">Hello World!</h1>
We are using node
<script> document.write(process.versions.node) </script>
Chrome
<script> document.write(process.versions.chrome) </script>,
and Electron
<script> document.write(process.versions.electron) </script>
</body>
</html>
複製代碼
最後,修改packge.json
中的main字段,並添加start命令
{
...
main:'index.js',
scripts:{
"start": "electron ."
}
}
複製代碼
執行npm run start
後,就會彈出咱們的應用來。
咱們知道electron有兩個進程,主進程和渲染進程,開發過程當中咱們須要怎麼去調試它們呢?老太太吃柿子,我們撿軟的來
BrowserWindow 用來建立和控制瀏覽器窗口,咱們調用它的實例上的API便可
win = new BrowserWindow({width: 800, height: 600})
win.webContents.openDevTools() // 打開調試
複製代碼
調試起來是和Chrome是同樣的,要不要這麼酸爽
使用VSCode進行調試
使用VSCode打開項目,點擊調試按鈕
點擊調試後的下拉框
選擇添加配置,選擇node
此時會把默認的調試配置打開,大概長這樣
什麼?你的不是,不是的話,就直接把下面的複製並替換你的配置
差很少這麼辦,那就把configurations
裏面第二項複製到你的configurations
配置裏面,第一個配置是用來調試node的
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "啓動程序",
"program": "${workspaceFolder}/main.js"
},
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args" : ["."]
}
]
}
複製代碼
能夠看到${workspaceFolder}
,這是關於VSCode的變量,用來表示當前打開的文件夾的路徑
修改完配置後,咱們調試面板,選擇咱們剛纔配置的
在代碼中標記須要調試的地方,而後點擊綠色的小三角,就能夠愉快的調試了
在Electron中, GUI 相關的模塊 (如 dialog、menu 等) 僅在主進程中可用, 在渲染進程中不可用。 爲了在渲染進程中使用它們, ipc 模塊是向主進程發送進程間消息所必需的,如下介紹幾種進程間通信的方法。
ipcMain和ipcRenderer是兩個好基友,經過這兩個模塊能夠實現進程的通訊。
ipcMain 在主進程中使用,用來處理渲染進程(網頁)發送的同步和異步的信息
ipcRenderer 在渲染進程中使用,用來發送同步或異步的信息給主進程,也能夠用來接收主進程的回覆信息。
以上兩個模塊的通訊,能夠理解成發佈訂閱模式
,接下來,咱們看下它們具體的使用方法
主進程
const {ipcMain} = require('electron')
// 監聽渲染程序發來的事件
ipcMain.on('something', (event, data) => {
event.sender.send('something1', '我是主進程返回的值')
})
複製代碼
渲染進程
const { ipcRenderer} = require('electron')
// 發送事件給主進程
ipcRenderer.send('something', '傳輸給主進程的值')
// 監聽主進程發來的事件
ipcRenderer.on('something1', (event, data) => {
console.log(data) // 我是主進程返回的值
})
複製代碼
以上代碼使用的是異步傳輸消息,electron也提供了同步傳輸的API。
發送同步消息將會阻塞整個渲染進程,你應該避免使用這種方式 - 除非你知道你在作什麼。
切忌用 ipc 傳遞大量的數據,會有很大的性能問題,嚴重會讓你整個應用卡住。
使用 remote 模塊, 你能夠調用 main 進程對象的方法, 而沒必要顯式發送進程間消息。
const { dialog } = require('electron').remote
dialog.showMessageBox({type: 'info', message: '在渲染進程中直接使用主進程的模塊'})
複製代碼
webContents負責渲染和控制網頁, 是 BrowserWindow 對象的一個屬性, 咱們使用send方法向渲染器進程發送異步消息。
主進程
const {app, BrowserWindow} = require('electron')
let win
app.on('ready', () => {
win = new BrowserWindow({width: 800, height: 600})
// 加載頁面
win.loadURL('./index.html')
// 導航完成時觸發,即選項卡的旋轉器將中止旋轉,並指派onload事件後。
win.webContents.on('did-finish-load', () => {
// 發送數據給渲染程序
win.webContents.send('something', '主進程發送到渲染進程的數據')
})
})
複製代碼
渲染進程
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script> require('electron').ipcRenderer.on('something', (event, message) => { console.log(message) // 主進程發送到渲染進程的數據 }) </script>
</body>
</html>
複製代碼
更多狀況下,咱們使用HTML5 API實現,如localStorage、sessionStorage等,也可使用electron的IPC機制實現
主進程
global.sharedObject = {
someProperty: 'default value'
}
複製代碼
渲染進程
第一個頁面
require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
複製代碼
第二個頁面
console.log(require('electron').remote.getGlobal('sharedObject').someProperty) // new value
複製代碼
以上四個方法都可實現主進程和渲染進程的通訊,能夠發現使用remote
模塊是最簡單的,渲染進程代碼中能夠直接使用electron
模塊
只有在應用聚焦的時候纔會觸發,主要代碼以下
官方文檔親測沒有效果
const { Menu, MenuItem } = require('electron')
const menu = new Menu()
menu.append(new MenuItem({
label: '自定義快捷鍵',
submenu: [
{
label: '測試',
accelerator: 'CmdOrCtrl+P',
click: () => {
console.log('我是本地快捷鍵')
}
}
]
}))
Menu.setApplicationMenu(menu)
複製代碼
註冊全局,不管應用是否聚焦,都會觸發,使用globalShortcut
來註冊, 主要代碼以下,
const {globalShortcut, dialog} = require('electron')
app.on('read', () => {
globalShortcut.register('CmdOrCtrl+1', () => {
dialog.showMessageBox({
type: 'info',
message: '你按下了全局註冊的快捷鍵'
})
})
})
複製代碼
顯示以下,使用了dialog
模塊
上下文菜單就是咱們點擊右鍵的時候顯示的菜單, 設置在渲染進程裏面
主要代碼以下
const remote = require('electron').remote; // 經過remote模塊使用主程序才能使用的模塊
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
var menu = new Menu();
menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));
menu.append(new MenuItem({ type: 'separator' }));
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }));
window.addEventListener('contextmenu', (e) => {
e.preventDefault();
menu.popup(remote.getCurrentWindow());
}, false);
複製代碼
上文中咱們經過Menu
模塊建立了本地快捷鍵,應用菜單也是用Menu
模塊,咱們看到長得好像同樣,其實實現起來也差很少,咱們這裏使用建立模版的方式來實現,主要代碼以下:
const {app, Menu} = require('electron')
const template = [
{
label: '操做',
submenu: [{
label: '複製',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
}, {
label: '粘貼',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
}, {
label: '從新加載',
accelerator: 'CmdOrCtrl+R',
click: function (item, focusedWindow) {
if (focusedWindow) {
// on reload, start fresh and close any old
// open secondary windows
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(function (win) {
if (win.id > 1) {
win.close()
}
})
}
focusedWindow.reload()
}
}
}]
},
{
label: '加載網頁',
submenu: [
{
label: '優酷',
accelerator: 'CmdOrCtrl+P',
click: () => { console.log('time to print stuff') }
},
{
type: 'separator'
},
{
label: '百度',
}
]
}
]
if (process.platform === 'darwin') {
const name = electron.app.getName()
template.unshift({
label: name,
submenu: [{
label: `關於 ${name}`,
role: 'about'
}, {
type: 'separator'
}, {
label: '服務',
role: 'services',
submenu: []
}, {
type: 'separator'
}, {
label: `隱藏 ${name}`,
accelerator: 'Command+H',
role: 'hide'
}, {
label: '隱藏其它',
accelerator: 'Command+Alt+H',
role: 'hideothers'
}, {
label: '顯示所有',
role: 'unhide'
}, {
type: 'separator'
}, {
label: '退出',
accelerator: 'Command+Q',
click: function () {
app.quit()
}
}]
})
}
app.on('read', () => {
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
})
複製代碼
主要代碼
const { app, Tray } = require('electron')
/* 省略其餘代碼 */
let tray;
app.on('ready', () => {
tray = new Tray(__dirname + '/build/icon.png');//系統托盤圖標
const contextMenu = Menu.buildFromTemplate([ // 菜單項
{label: '顯示', type: 'radio', click: () => {win.show()}},
{label: '隱藏', type: 'radio', click: () => {win.hide()}},
])
// tray.on('click', () => { // 鼠標點擊事件最好和菜單隻設置一種
// win.isVisible() ? win.hide() : win.show()
// })
tray.setToolTip('This is my application.') // 鼠標放上時候的提示
tray.setContextMenu(contextMenu) // 應用菜單項
})
複製代碼
主進程打開頁面,會調用默認的瀏覽器打開頁面,使用shell
模塊
const { app,shell } = require('electron')
app.on('ready', () => {
shell.openExternal('github.com')
})
複製代碼
應用啓動後就會使用默認瀏覽器打開github
頁面
渲染進程中使用,當前應用打開頁面
window.open('github.com')
複製代碼
使用webview
能夠在一個獨立的 frame 和進程裏顯示外部 web 內容
直接在index.html中使用便可
<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>
複製代碼
其餘應用模塊和API請下載
electron-forge包含vue
、react
、Angular
等開箱即用的模版。
npm i -g electron-forge
electron-forge init my-app template=react
cd my-app
npm run start
複製代碼
目錄結構以下
.compilerc
是electron-compile
的配置文件,和.babelrc
相似
electron-compile是一種轉換規則,支持在應用程序中編譯js和css
若是你不但願任何工具,而想要簡單地從一個模板開始構建,react-electron模版能夠了解下。
electron-react-boilerplate 是雙package.json
配置項目, 目錄以下
electron-vue充分利用 vue-cli 做爲腳手架工具,加上擁有 vue-loader 的 webpack、electron-packager 或是 electron-builder,以及一些最經常使用的插件,如vue-router、vuex 等等。
目錄結構以下
更多模版請訪問
怎麼將咱們開發好的應用打包成.app
或.exe
的執行文件,這就涉及到了重要的打包環節, 這裏使用electron-quick-start項目進行打包
目前,主流的打包工具備兩個electron-packager和electron-builder
Mac打包window安裝包需下載wine
brew install wine
若是有丟失組件,按照報錯信息進行下載便可
electron-packager把你的electron打包成可運行文件(.app, .exe, etc)
執行npm i electron-packager -D
進行安裝
electron-packager .
快速打包
electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --out=out --icon=assets/app.ico --asar --overwrite --ignore=.git
複製代碼
darwin, linux, mas, win32 all
ia32,x64,armv7l,arm64
第一次打包須要下載二進制的包耗時會久一些,之後走緩存就快的多了。
打包後目錄爲
其中electron-quick-start
能夠直接打開運行
緩存地址
~/Library/Caches/electron/
$LOCALAPPDATA/electron/Cache
or ~/AppData/Local/electron/Cache/
$XDG_CACHE_HOME
or ~/.cache/electron/
electron-builder是一個完整的解決方案,對於macos、windows、linux下的electron app,它能夠提供打包及構建的相關功能。同時,它還提供開箱即用的「自動更新」功能支持
npm i electron-builder -D
下載
electron-builder
打包
出現以下
一樣是第一次打包時間會比較長,彆着急,靜候佳音。
會默認打包在dist
目錄,包含以下
mac
文件裏有運行時文件
,默認使用asar方式進行打包
electron-builder --dir
只會生成包文件,對測試有用
坑坑坑
第一次打包的時候會比較慢,若是你和我手欠直接退出了,再次打包的時候,恭喜你,出錯了。報錯信息以下
• electron-builder version=20.28.2
• loaded configuration file=package.json ("build" field)
• description is missed in the package.json appPackageFile=/Users/shisan/Documents/self/you-app/package.json
• writing effective config file=dist/builder-effective-config.yaml
• no native production dependencies
• packaging platform=darwin arch=x64 electron=2.0.7 appOutDir=dist/mac
• cannot unpack electron zip file, will be re-downloaded error=zip: not a valid zip file
⨯ zip: not a valid zip file
Error: /Users/shisan/Documents/self/you-app/node_modules/app-builder-bin/mac/app-builder exited with code 1
at ChildProcess.childProcess.once.code (/Users/shisan/Documents/self/you-app/node_modules/builder-util/src/util.ts:254:14)
at Object.onceWrapper (events.js:272:13)
at ChildProcess.emit (events.js:180:13)
at maybeClose (internal/child_process.js:936:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:220:5)
From previous event:
at unpack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/out/electron/ElectronFramework.js:191:18)
at Object.prepareApplicationStageDirectory (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/electron/ElectronFramework.ts:148:50)
at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:179:21
at Generator.next (<anonymous>)
From previous event:
at MacPackager.doPack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:166:165)
at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:88:63
at Generator.next (<anonymous>)
From previous event:
at MacPackager.pack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:80:95)
at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:376:24
at Generator.next (<anonymous>)
at xfs.stat (/Users/shisan/Documents/self/you-app/node_modules/fs-extra-p/node_modules/fs-extra/lib/mkdirs/mkdirs.js:56:16)
at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/polyfills.js:287:18
at FSReqWrap.oncomplete (fs.js:171:5)
From previous event:
at Packager.doBuild (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:344:39)
at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:314:57
at Generator.next (<anonymous>)
at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:99:16
at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:43:10
at FSReqWrap.oncomplete (fs.js:153:20)
From previous event:
at Packager._build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:285:133)
at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:281:23
at Generator.next (<anonymous>)
From previous event:
at Packager.build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:238:14)
at build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/index.ts:58:28)
at build (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/builder.ts:227:10)
at then (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48)
at runCallback (timers.js:763:18)
at tryOnImmediate (timers.js:734:5)
at processImmediate (timers.js:716:5)
From previous event:
at Object.args [as handler] (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48)
at Object.runCommand (/Users/shisan/Documents/self/you-app/node_modules/yargs/lib/command.js:237:44)
at Object.parseArgs [as _parseArgs] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1085:24)
at Object.get [as argv] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1000:21)
at Object.<anonymous> (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:25:28)
at Module._compile (internal/modules/cjs/loader.js:654:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
at Module.load (internal/modules/cjs/loader.js:566:32)
at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
at Function.Module._load (internal/modules/cjs/loader.js:498:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:695:10)
at startup (internal/bootstrap/node.js:201:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! you-app@1.0.0 dist: `electron-builder --mac --x64`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the you-app@1.0.0 dist script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/shisan/.npm/_logs/2018-08-22T06_28_55_102Z-debug.log
✖ Error building interactive interface
複製代碼
問題是在下載.zip包的時候,中斷了操做,之後全部執行打包的時候,找不到那個文件(或者是殘缺的文件)就報錯了,須要手動清除下緩存 緩存路徑在~/Library/Caches/electron/
electron-builder
配置文件寫在package.json
中的build
字段中
"build": {
"appId": "com.example.app", // 應用程序id
"productName": "測試", // 應用名稱
"directories": {
"buildResources": "build", // 構建資源路徑默認爲build
"output": "dist" // 輸出目錄 默認爲dist
},
"mac": {
"category": "public.app-category.developer-tools", // 應用程序類別
"target": ["dmg", "zip"], // 目標包類型
"icon": "build/icon.icns" // 圖標的路徑
},
"dmg": {
"background": "build/background.tiff or build/background.png", // 背景圖像的路徑
"title": "標題",
"icon": "build/icon.icns" // 圖標路徑
},
"win": {
"target": ["nsis","zip"] // 目標包類型
}
}
複製代碼
使用electron-package或者electron-builder進行打包,就不須要asar手動打包了,這兩個工具已經集成進去了,如下內容只作瞭解便可
asar是一種將多個文件合併成一個文件的類 tar 風格的歸檔格式。 Electron 能夠無需解壓整個文件,便可從其中讀取任意文件內容。
上面咱們看到使用electron-package
進行打包的時候,能夠添加--asar
參數, 它的做用就是將咱們的源碼打包成asar格式, 不使用的話就是咱們的源碼。
依舊使用electron-quick-start
模版, 使用electron-package
進行打包
打包後目錄中選擇應用,右鍵顯示包內容
依次打開路徑 Contents -> Resources -> app
就能夠看到咱們的原文件了
使用electron-package . --asar
進行打包,再次查看app中的源文件已經打包成asar
文件了
asar pack|p <dir> <ouput>
複製代碼
如 asar ./ app.asar
asar extract|e <archive> <output>
複製代碼
如 asar e app.asar ./
事實上,就算使用了asar打包方式,咱們的源代碼依舊是暴露的,使用asar解壓仍然能輕易解密,使用webpack將代碼壓縮混淆纔是王道。
咱們使用electron-builder和electron-updater來完成應用的自動更新, 並非electron裏面的autoUpdater
不管使用哪一種方式進行自動更新,代碼簽名是必不可少的,咱們使用建立本地的證書來進行測試自動更新
在其餘中找到鑰匙串訪問
依次選擇 鑰匙串訪問
-> 證書助理
-> 建立證書
,建立一個新的證書
起個響亮的名字,證書類型選擇代碼簽名
,而後點擊建立
建立完成後在鑰匙串中找到它
右鍵,選擇更改信任設置,將信任設置成始終信任
沒有代碼簽名
代碼簽名
執行sudo vi ~/.bash_profile
, 添加變量
export CSC_NAME="electron_update"
複製代碼
執行source ~/.bash_profile
重載變量文件
執行echo $CSC_NAME
查看變量有沒有生效,沒有生效的話,執行上面命令重載文件
屢次重載,依舊獲取不到變量,直接退出終端,再次登陸終端便可
使用electron-builder
進行打包,項目使用electron-quick-start
咱們先添加打包的build
配置, 在package.json
中添加
"build": {
"appId": "org.electron.com",
"publish": [
{
"provider": "generic",
"url": "http://172.28.86.36:8080/"
}
],
"productName": "個人",
"directories": {
"output": "dist"
},
"mac": {
"target": [
"dmg",
"zip"
]
},
"win": {
"target": [
"nsis",
"zip"
]
},
"dmg": {
"backgroundColor": "red",
"title": "made",
"contents": [
{
"x": 400,
"y": 128,
"type": "link",
"path": "/Applications"
}
]
}
}
複製代碼
前面,咱們說過了build
字段中各個參數的含義,這裏就不贅述了,這裏添加了publish
字段,它是配置咱們自動更新的信息,url是服務器地址。
服務器咱們可使用http-server模塊, 快速搭建一個靜態服務器
執行打包後,輸出
主要看下latest-mac.yml
文件
能夠看到version
字段,用來代表當前應用的版本,那這個字段是從哪來的呢?
沒錯就是咱們的package.json
文件中version
字段
在主進程中寫入如下代碼
const {app, BrowserWindow, ipcMain} = require('electron')
const { autoUpdater } = require('electron-updater')
// 本地服務器地址
const feedURL = `http://172.28.82.40:8080/`
let mainWindow
function createWindow () { // 建立窗口
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadFile('index.html')
mainWindow.on('closed', function () {
mainWindow = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})
// 監聽自定義update事件
ipcMain.on('update', (e, arg) => {
checkForUpdate()
})
const checkForUpdate = () => {
// 設置檢查更新的 url,而且初始化自動更新
autoUpdater.setFeedURL(feedURL)
// 監聽錯誤
autoUpdater.on('error', message => {
sendUpdateMessage('err', message)
})
// 當開始檢查更新的時候觸發
autoUpdater.on('checking-for-update', message => {
sendUpdateMessage('checking-for-update', message);
})
//
autoUpdater.on('download-progress', function(progressObj) {
sendUpdateMessage('downloadProgress', progressObj);
});
// 更新下載完成事件
autoUpdater.on('update-downloaded', function(event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
ipcMain.on('updateNow', (e, arg) => {
autoUpdater.quitAndInstall();
});
sendUpdateMessage('isUpdateNow');
});
// 向服務端查詢如今是否有可用的更新
autoUpdater.checkForUpdates();
}
// 發送消息觸發message事件
function sendUpdateMessage(message, data) {
mainWindow.webContents.send('message', { message, data });
}
複製代碼
而後更改咱們的渲染進程的代碼
const {ipcRenderer} = require ('electron');
const button = document.querySelector('#button')
const ul = document.querySelector('ul')
button.onclick = () => {
ipcRenderer.send('update')
}
ipcRenderer.on('message', (event, {message,data }) => {
let li = document.createElement('li')
li.innerHTML = message + " <br>data:" + JSON.stringify(data) +"<hr>";
ul.appendChild(li)
if (message === 'isUpdateNow') {
if (confirm('是否如今更新?')) {
ipcRenderer.send('updateNow');
}
}
})
複製代碼
頁面代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<h1>當前版本是1.0.3</h1>
<ul>
<li>生命週期過程展現</li>
</ul>
<button id="button">點擊我</button>
<script> // You can also require other files to run in this process require('./renderer.js') </script>
</body>
</html>
複製代碼
這裏使用按鈕點擊事件觸發更新操做。
直接打包,安裝這個1.0.3
的版本。
而後將package.json
的文件中的version
字段更改爲1.0.5
,將index.html的更改爲1.0.5
,進行打包。
隨便找個地方建立個文件夾,如test
將打包的文件移動到test
中,執行http-server ./
,搭建服務
當咱們點擊按鈕的時候,就能夠進行更新應用了,以下圖
點擊ok後,靜候片刻,更新完後就打開了最新版本的應用
以上就完成了electron的自動更新。
本文全部代碼請戳github瞭解更多
ocr相關demo借(chao)鑑(xi)了Jartto
的electron-ocr
,下文有連接。
Electron 打包Mac安裝包代碼簽名問題解決方案
文中所說簽名均須要是買了Apple開發者帳號的。