调研结论
- 应用更新官网对升级服务器有两种对应方案:具体如下方案一及方案二
- window 环境自动更新不一定非要https http也可以。mac 下必须要是https
- 升级过程的相关思路
- 比较版本
- 升级下载
- 自动升级/手动升级
方案一:update.electronjs.org
满足条件
- 应用运行在 macOS 或者 Windows
- 应用有公开的 GitHub 仓库
- 编译的版本发布在 GitHub Releases
- 编译的版本已代码签名
参考文档
自动更新功能开发时注意项
项目中用到window.print网页打印。在提升elecreon-builder版本后,打印时样式总是显示不对。elecreon-builder 的版本必须要低于20,不然就会出现这个问题。
当electron-builder 版本升级后,老的版本不能直接通过自动升级升上去。
当只跟新electron-update版本时,可以自动升级,但当当前是最新的时候点击升级会提示更新失败
当提示electron-update…至少4.0.0时,需要将electron-update放入devDependencies 中。
方案二:构建自己的更新服务器
参考文档
客户端
升级方案
调研结论
- 应用更新官网对升级服务器有两种对应方案:具体如下方案一及方案二
- window 环境自动更新不一定非要https http也可以。mac 下必须要是https
- 升级过程的相关思路
- 比较版本
- 升级下载
- 自动升级/手动升级
方案一:update.electronjs.org
满足条件
- 应用运行在 macOS 或者 Windows
- 应用有公开的 GitHub 仓库
- 编译的版本发布在 GitHub Releases
- 编译的版本已代码签名
参考文档
自动更新功能开发时注意项
项目中用到window.print网页打印。在提升elecreon-builder版本后,打印时样式总是显示不对。elecreon-builder 的版本必须要低于20,不然就会出现这个问题。
当electron-builder 版本升级后,老的版本不能直接通过自动升级升上去。
当只跟新electron-update版本时,可以自动升级,但当当前是最新的时候点击升级会提示更新失败
当提示electron-update…至少4.0.0时,需要将electron-update放入devDependencies 中。
方案二:构建自己的更新服务器
参考文档
客户端
升级方案
其他写法具体方案
安装==electron-updater==
npm install electron-updater --save
修改packpage.json
"publish": [
{
"provider": "generic",
"url": "http://自己ip/app/update"
}
],
核心方法
主进程 主要是==handleUpdate==方法
import {app, BrowserWindow, ipcMain} from 'electron'
// 注意这个autoUpdater不是electron中的autoUpdater
import {autoUpdater} from "electron-updater"
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
*/
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
let mainWindow
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080`
: `file://${__dirname}/index.html`
function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000
})
mainWindow.loadURL(winURL)
mainWindow.on('closed', () => {
mainWindow = null
});
//处理更新操作
function handleUpdate() {
const returnData = {
error: {status: -1, msg: '检测更新查询异常'},
checking: {status: 0, msg: '正在检查应用程序更新'},
updateAva: {status: 1, msg: '检测到新版本,正在下载,请稍后'},
updateNotAva: {status: -1, msg: '您现在使用的版本为最新版本,无需更新!'},
};
//和之前package.json配置的一样
autoUpdater.setFeedURL('http://xxx.com/app/update');
//更新错误
autoUpdater.on('error', function (error) {
sendUpdateMessage(returnData.error)
});
//检查中
autoUpdater.on('checking-for-update', function () {
sendUpdateMessage(returnData.checking)
});
//发现新版本
autoUpdater.on('update-available', function (info) {
sendUpdateMessage(returnData.updateAva)
});
//当前版本为最新版本
autoUpdater.on('update-not-available', function (info) {
setTimeout(function () {
sendUpdateMessage(returnData.updateNotAva)
}, 1000);
});
// 更新下载进度事件
autoUpdater.on('download-progress', function (progressObj) {
mainWindow.webContents.send('downloadProgress', progressObj)
});
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
ipcMain.on('isUpdateNow', (e, arg) => {
//some code here to handle event
autoUpdater.quitAndInstall();
});
// win.webContents.send('isUpdateNow')
});
//执行自动更新检查
autoUpdater.checkForUpdates();
}
handleUpdate();
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
mainWindow.webContents.send('message', text)
}
ipcMain.on("checkForUpdate", (event, data) => {
console.log('执行自动更新检查!!!');
// event.sender.send('reply', 'hi lee my name is yuan, age is 17');
autoUpdater.checkForUpdates();
});
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
});
有更新包即会触发
autoUpdater.on('download-progress', function (progressObj) {
// mainWindow.webContents.send('downloadProgress', progressObj)
const winId = BrowserWindow.getFocusedWindow().id;
let win = BrowserWindow.fromId(winId);
win.webContents.send('downloadProgress', progressObj)
});
progressObj 返回的对象
- bytesPerSecond: bps/s //传送速率
- percent : 百分比
- total : 总大小
- transferred: 已经下载
使用==ipcRenderer==用于监听和发送消息向主进程
api官网地址
ipcRenderer.on 监听事件
ipcRenderer.send 发送事件
此方案实现参考地址
其他写法具体方案
安装==electron-updater==
npm install electron-updater --save
修改packpage.json
"publish": [
{
"provider": "generic",
"url": "http://自己ip/app/update"
}
],
核心方法
主进程 主要是==handleUpdate==方法
import {app, BrowserWindow, ipcMain} from 'electron'
// 注意这个autoUpdater不是electron中的autoUpdater
import {autoUpdater} from "electron-updater"
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
*/
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
let mainWindow
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080`
: `file://${__dirname}/index.html`
function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000
})
mainWindow.loadURL(winURL)
mainWindow.on('closed', () => {
mainWindow = null
});
//处理更新操作
function handleUpdate() {
const returnData = {
error: {status: -1, msg: '检测更新查询异常'},
checking: {status: 0, msg: '正在检查应用程序更新'},
updateAva: {status: 1, msg: '检测到新版本,正在下载,请稍后'},
updateNotAva: {status: -1, msg: '您现在使用的版本为最新版本,无需更新!'},
};
//和之前package.json配置的一样
autoUpdater.setFeedURL('http://xxx.com/app/update');
//更新错误
autoUpdater.on('error', function (error) {
sendUpdateMessage(returnData.error)
});
//检查中
autoUpdater.on('checking-for-update', function () {
sendUpdateMessage(returnData.checking)
});
//发现新版本
autoUpdater.on('update-available', function (info) {
sendUpdateMessage(returnData.updateAva)
});
//当前版本为最新版本
autoUpdater.on('update-not-available', function (info) {
setTimeout(function () {
sendUpdateMessage(returnData.updateNotAva)
}, 1000);
});
// 更新下载进度事件
autoUpdater.on('download-progress', function (progressObj) {
mainWindow.webContents.send('downloadProgress', progressObj)
});
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
ipcMain.on('isUpdateNow', (e, arg) => {
//some code here to handle event
autoUpdater.quitAndInstall();
});
// win.webContents.send('isUpdateNow')
});
//执行自动更新检查
autoUpdater.checkForUpdates();
}
handleUpdate();
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
mainWindow.webContents.send('message', text)
}
ipcMain.on("checkForUpdate", (event, data) => {
console.log('执行自动更新检查!!!');
// event.sender.send('reply', 'hi lee my name is yuan, age is 17');
autoUpdater.checkForUpdates();
});
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
});
有更新包即会触发
autoUpdater.on('download-progress', function (progressObj) {
// mainWindow.webContents.send('downloadProgress', progressObj)
const winId = BrowserWindow.getFocusedWindow().id;
let win = BrowserWindow.fromId(winId);
win.webContents.send('downloadProgress', progressObj)
});
progressObj 返回的对象
- bytesPerSecond: bps/s //传送速率
- percent : 百分比
- total : 总大小
- transferred: 已经下载
使用==ipcRenderer==用于监听和发送消息向主进程
api官网地址
ipcRenderer.on 监听事件
ipcRenderer.send 发送事件