Electron autoUpdater實(shí)現(xiàn)Windows安裝包自動(dòng)更新的方法
前言
Electron幫助我們突破瀏覽器的界限,通過(guò)Electron構(gòu)建的桌面應(yīng)用擁有各種瀏覽器應(yīng)用夢(mèng)寐以求的能力。
Electron提供的autoUpdater還可以幫助我們實(shí)現(xiàn)桌面應(yīng)用的自動(dòng)更新。
文件結(jié)構(gòu)
首先,我們已經(jīng)有了一個(gè)基于Electron做的應(yīng)用,項(xiàng)目中有兩個(gè)package.json。這樣做的一個(gè)原因是將devDependencies和dependencies分開了,另外就是不需要在打包的時(shí)候再去指定哪些依賴不需要一起打到安裝包里面去了(通過(guò)ignore參數(shù))。
目錄結(jié)構(gòu)類似于這樣:
myapp
-node_modules
-package.json
-app
-js
-css
-index.html
-main.js
-package.json
外面的package.json內(nèi)容類似于:
{
"name": "myapp",
"main": "app/main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron-prebuilt": "^1.2.7"
}
}
里面的package.json的內(nèi)容類似于:
{
"name": "myapp",
"version": "1.0",
"main": "main.js",
"description": "my app",
"scripts": {
"start": "electron ."
},
"dependencies": {}
}
注意里面的package.json中的name,version,description是必填的,接下來(lái)打包會(huì)用到。
electron-squirrel-startup
為了使最后的安裝包能夠?qū)崿F(xiàn)自動(dòng)更新,我們需要對(duì)現(xiàn)有的應(yīng)用做一些改動(dòng),使它可以處理一些啟動(dòng)或者安裝時(shí)的事件。
我們可以在main.js里面加入一些處理的代碼或者方便起見,我們可以直接使用electron-squirrel-startup。
先安裝:
npm install electron-squirrel-startup --save
因?yàn)樾枰趍ain.js里面用到,我們需要將其安裝在app里面。
在main.js里面使用它,第一行加入如下代碼即可:
if (require('electron-squirrel-startup')) return;
有興趣的童鞋可以一起跟我去看看electron-squirrel-startup做了什么事情,急著打包的童鞋可以直接忽略這一段:
在myapp/app/node_modules/electron-squirrel-startup下面有一個(gè)index.js:
var path = require('path');
var spawn = require('child_process').spawn;
var debug = require('debug')('electron-squirrel-startup');
var app = require('electron').app;
var run = function(args, done) {
var updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
debug('Spawning `%s` with args `%s`', updateExe, args);
spawn(updateExe, args, {
detached: true
}).on('close', done);
};
var check = function() {
if (process.platform === 'win32') {
var cmd = process.argv[1];
debug('processing squirrel command `%s`', cmd);
var target = path.basename(process.execPath);
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
run(['--createShortcut=' + target + ''], app.quit);
return true;
}
if (cmd === '--squirrel-uninstall') {
run(['--removeShortcut=' + target + ''], app.quit);
return true;
}
if (cmd === '--squirrel-obsolete') {
app.quit();
return true;
}
}
return false;
};
module.exports = check();
它的代碼只有短短幾十行,做的事情也很簡(jiǎn)單,注意返回值為true的那幾行,基本上來(lái)說(shuō)就是安裝時(shí),更新完成時(shí),卸載時(shí) main.js都會(huì)被調(diào)用,我們需要根據(jù)不同的情況做不同的事情,完成這些事情后不要啟動(dòng)應(yīng)用(會(huì)出錯(cuò)),直接退出就好。
正常啟動(dòng)前我們需要去檢測(cè)是否有新的安裝包,之后下載新包,重新安裝,重啟應(yīng)用,為了做到這一點(diǎn),我們需要在main.js里面加入如下代碼:
app.on('ready', () => {
//安裝后第一次啟動(dòng)不去檢測(cè)更新,go做的事情就是啟動(dòng)我們的應(yīng)用
if (process.argv[1] == '--squirrel-firstrun') {
go();
return;
}
/* 設(shè)置自動(dòng)更新的feedURL,本地測(cè)試可以設(shè)置為類似于http://127.0.0.1:8080/latest
* 在latest文件夾下放著三個(gè)我們的安裝文件(Setup.exe,RELEASES,myapp-1.0-full.nupkg),下面會(huì)講到
* /
autoUpdater.setFeedURL(feedURL);
autoUpdater.on('update-downloaded', function() {
// 下載完成,更新前端顯示
autoUpdater.quitAndInstall();
});
try {
// 不是安裝應(yīng)用的情況下啟動(dòng)下回出錯(cuò),此時(shí)直接正常啟動(dòng)應(yīng)用
autoUpdater.checkForUpdates();
} catch (ex) {
go();
return;
}
// createWindow是我們自己定義的方法,用來(lái)創(chuàng)建窗口,此處用來(lái)創(chuàng)建檢測(cè)更新的窗口
createWindow({
name: 'updateWindow',
url: 'check-for-updates.html',
title: "checkForUpdates",
icon: icon,
frame: false,
width: 1306,
height: 750
});
});
自動(dòng)更新后臺(tái)搭建
var express = require('express');
var app = express();
app.use(express.static('releases'));
var server = app.listen(8080, function() {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port);
});
文件結(jié)構(gòu)如下:
autoupdate-backend
-package.json
-index.js
-node_modules
-releases
-latest
此時(shí)latest文件夾里面還是空的,之后我們開始打包,將打包出來(lái)的三個(gè)文件放在此處即可。
electron-packager
在myapp下安裝:
npm install electron-packager --save-dev npm install electron-packager -g
兩種安裝方式對(duì)應(yīng)兩種使用方式,第一種在腳本中使用,第二種的命令行使用。
腳本中使用,小姐姐在這里借助了gulp,所以需要安裝gulp:
npm install gulp --save-dev npm install gulp -g
新建GulpFile.js,定義一個(gè)task:
var gulp = require('gulp');
var platform = 'win32';
var arch = 'ia32';
var appPath = 'app';
var packageOutPath = 'production/package';
var iconPath = 'app/favicon.ico';
gulp.task('generate-package', () => {
generatePackage();
});
function generatePackage(callback) {
var packager = require('electron-packager')
packager({
dir: appPath,
platform: platform,
arch: arch,
out: packageOutPath,
icon: iconPath,
/*桌面快捷方式名稱以及開始菜單文件夾名稱*/
'version-string': {
CompanyName: 'MyCompany Inc.',
ProductName: 'myapp'
}
}, function (err) {
if (err) {
console.log(err);
} else {
callback && callback();
}
});
}
需要打包的時(shí)候,打開命令行:
gulp generate-package
這樣做的好處是調(diào)用方便,當(dāng)然我們也可以直接通過(guò)命令行調(diào)用electron-packager,前提是我們?nèi)职惭b了它或者將其安裝目錄添加到了環(huán)境變量中:
更多參數(shù)一一加上即可。
貼上官方文檔鏈接:
github鏈接:https://github.com/electron-userland/electron-packager
下面兩個(gè)鏈接在上面的文檔里面都能找到,但是個(gè)人感覺比較常用,還是貼出來(lái):
參數(shù)使用:https://github.com/electron-userland/electron-packager/blob/master/usage.txt
腳本使用:https://github.com/electron-userland/electron-packager/blob/master/docs/api.md
打包
myapp下安裝electron-winstaller:
npm install electron-winstaller --save-dev
還是在gulp里面添加一個(gè)task,連同package的代碼一起貼上:
var gulp = require('gulp');
var platform = 'win32';
var arch = 'ia32';
var appPath = 'app';
var outName = 'myapp-win32-' + arch;
var packageOutPath = 'production/package';
var installerOutPath = 'production/installer';
var packagePath = `${packageOutPath}/${outName}`;
var installerPath = `${installerOutPath}/${outName}`;
var iconPath = 'app/favicon.ico';
var gifPath = 'loading.gif';
gulp.task('generate-package', () => {
generatePackage();
});
gulp.task('generate-installer', () => {
isDirExist(packagePath, (exist) => {
if (exist) {
generateInstaller();
} else {
generatePackage(() => {
generateInstaller();
});
}
});
});
function isDirExist(path, callback) {
fs.readdir(path, (err) => {
callback && callback(!err);
});
}
function generatePackage(callback) {
var packager = require('electron-packager')
packager({
dir: appPath,
platform: platform,
arch: arch,
out: packageOutPath,
icon: iconPath,
/*桌面快捷方式名稱以及開始菜單文件夾名稱*/
'version-string': {
CompanyName: 'MyCompany Inc.',
ProductName: 'myapp'
}
}, function (err) {
if (err) {
console.log(err);
} else {
callback && callback();
}
});
}
function generateInstaller() {
var electronInstaller = require('electron-winstaller');
electronInstaller.createWindowsInstaller({
appDirectory: packagePath,
outputDirectory: installerPath,
loadingGif: gifPath,
authors: 'ganyouyin',
exe: 'myapp.exe',
title: 'My APP',
iconUrl: `${__dirname}/${iconPath}`,
setupIcon: iconPath,
setupExe: 'Setup.exe',
noMsi: true
}).then(() => console.log("It worked!"), (e) => console.log(`No dice: ${e.message}`));
}
之后執(zhí)行任務(wù):
gulp generate-installer
第一次會(huì)非常慢,但是執(zhí)行完成后我們的安裝包就出來(lái)了。
此時(shí)我們的文件結(jié)構(gòu)是:
myapp
-GulpFile.js
-package.json
-node_modules
-app
-production
-package
-myapp-win32-ia32
- 各種文件,包含一個(gè)myapp.exe,雙擊可以直接運(yùn)行
-installer
-myapp-win32-ia32
-Setup.exe
-RELEASES
-myapp-1.0-full.nupkg
有了三個(gè)文件,將他們粘到之前的autoupdate-backend/releases/latest文件夾下面。
測(cè)試
- 啟動(dòng)我們的自動(dòng)更新后臺(tái);
- 將myapp/app下的package.json里面的version改為1.1,再次打包;
- 將之前的autoupdate-backend中的latest文件夾重命名為1.0;
- 新建文件夾latest,將新打包產(chǎn)生的三個(gè)文件粘進(jìn)去;
- 雙擊1.0里面的Setup.exe安裝應(yīng)用;
- 關(guān)閉應(yīng)用,雙擊桌面上的快捷方式myapp.exe再次打開應(yīng)用;
不出意外此時(shí)就會(huì)去進(jìn)行自動(dòng)更新的操作,結(jié)束后自動(dòng)重啟,再次打開時(shí)已經(jīng)是1.1的應(yīng)用。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C#開發(fā)windows服務(wù)實(shí)現(xiàn)自動(dòng)從FTP服務(wù)器下載文件
- Windows下支持自動(dòng)更新的Electron應(yīng)用腳手架的方法
- windows長(zhǎng)時(shí)間保持遠(yuǎn)程桌面不被自動(dòng)斷開
- 在Windows環(huán)境下使用MySQL:實(shí)現(xiàn)自動(dòng)定時(shí)備份
- windows mysql 自動(dòng)備份的幾種方法匯總
- 在Windows下自動(dòng)備份PostgreSQL的教程
- Windows系統(tǒng)自動(dòng)連接網(wǎng)絡(luò)共享打印機(jī)BAT腳本分享
- windows10徹底關(guān)閉自動(dòng)更新【絕對(duì)可行】
相關(guān)文章
基于ssm框架實(shí)現(xiàn)layui分頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了基于ssm框架實(shí)現(xiàn)layui分頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
uniapp項(xiàng)目實(shí)踐之全局公共組件樣式及方法使用示例詳解
這篇文章主要為大家介紹了uniapp項(xiàng)目實(shí)踐之全局公共組件樣式及方法使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
非主流的textarea自增長(zhǎng)實(shí)現(xiàn)js代碼
今天稍微研究了下textarea隨輸入內(nèi)容自動(dòng)增長(zhǎng)的功能,通過(guò)google參考了一些實(shí)現(xiàn)方式2011-12-12
javascript游戲開發(fā)之《三國(guó)志曹操傳》零部件開發(fā)(二)人物行走的實(shí)現(xiàn)
上一講我們談到了如何讓靜態(tài)人物變?yōu)閯?dòng)態(tài),今天我們來(lái)談?wù)勅绾问谷宋镆苿?dòng),感興趣的朋友可以了解下哦,順便鞏固一下animate方法的應(yīng)用,希望本文對(duì)你有所幫助2013-01-01
livereload工具實(shí)現(xiàn)前端可視化開發(fā)【推薦】
本文將介紹一個(gè)工具--livereload。這是一款能根據(jù)你本地文件(html、css、js)的變化,自動(dòng)跟蹤刷新瀏覽器的實(shí)時(shí)刷新工具,有了這個(gè)工具,會(huì)大大減輕你刷新頁(yè)面的工作量。下面跟著小編一起來(lái)看下吧2016-12-12
JavaScript使用表單元素驗(yàn)證表單的示例代碼
這篇文章主要介紹了JavaScript使用表單元素驗(yàn)證表單的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08

