如何使用electron-builder及electron-updater給項目配置自動更新
說明:
本文的自動更新功能使用的項目為 electron-vue 腳手架搭建一個默認項目。
參考的文章如下:
- electron-vue 中文文檔
- electron-builder 文檔
- Windows 下支持自動更新的 Electron 應用腳手架
- Electron 文檔 Docs / API / autoUpdater
開始:新建一個 electron 項目
首先你得有一個需要配置自動更新功能的 electron 項目。這里我為了測試自動更新功能是否成功搭建使用的是 electron-vue 腳手架搭建的項目。
搭建過程如下:
# 安裝 vue-cli 和 腳手架樣板代碼 npm install -g vue-cli vue init simulatedgreg/electron-vue autoUpdataTest # 安裝依賴并運行你的程序 cd autoUpdataTest npm install npm run dev
程序運行后的界面如下:

腳手架生成的文件結構:
|- autoUpdateTest |- .electron-vue # 壓縮及運行環(huán)境的配置文件 |- build # |- icons # 圖標文件 |- ... # 打包生成的文件在此處 |- dist # 用 webpack 壓縮項目后生成的壓縮文件在此處 |- node_modules |- src # 資源文件 |- main # 主進程 |- renderer # 渲染進程 |- index.ejx # 入口文件 |- static # 靜態(tài)資源 |- .babelrc |- .gitignore |- .travis |- appveyor.yml |- package-lock.json # npm 自動生成的文件 |- package.json |- README.md
使用 electron-builder 最關鍵的配置在 package.json 里:(為了觀察我們所需要的地方,把此篇文章里不需要關注的代碼給刪掉了。)
{
"name": "autoupdatetest",
"version": "0.0.0",
"author": "wonder <xxxxxxxxx@qq.com>",
"description": "An electron-vue project",
"main": "./dist/electron/main.js",
"scripts": {
"build": "node .electron-vue/build.js && electron-builder",
"dev": "node .electron-vue/dev-runner.js",
},
"build": {
"productName": "autoupdateteset",
"appId": "org.simulatedgreg.electron-vue",
"directories": {
"output": "build"
},
"files": "dist/electron/**/*",
"win": {
"icon": "build/icons/icon.ico"
}
},
"dependencies": {
},
"devDependencies": {
}
}
解析:
前四行是一般的 package.json 會有的:
name— 項目名version— 版本號author— 開發(fā)人員及郵箱號description— 項目描述 。
下面重點看后面的內容:electron-builder詳細配置文檔
- "main": "./dist/electron/main.js" — 這里的 main 入口文件指的是用 electron-builder 打包主程序的入口文件,這里的路徑是使用 webpack 壓縮項目后文件輸出的位置。
- scripts — 腳本
- "build": "node .electron-vue/build.js && electron-builder" — 生產環(huán)境,壓縮打包項目。先運行 .electron-vue 文件夾下的 build.js 腳本對項目進行壓縮,輸出的位置在 dist 文件夾下,然后再使用配置好的 electron-builder 對 dist 文件夾下的文件進行打包生成應用的安裝包。
- "dev": "node .electron-vue/dev-runner.js" — 開發(fā)環(huán)境,可以運行我們的項目并測試。這里使用了熱更新,改動代碼不需要刷新即可看到應用的改變。
- build — electron-builder 配置項
- "productName": "autoupdateteset", — 工程項目名
- "appId": "org.simulatedgreg.electron-vue" — 應用程序 ID。強烈建議設置顯式ID。
- directories
- "output": "build" — 生成的安裝包輸出目錄。
- "files": "dist/electron/**/*" — 安裝包源文件目錄,支持多路徑(數組)
- "win": { "icon": "build/icons/icon.ico"} — 打包成 Windows 系統(tǒng)下安裝包應用程序圖標路徑,還有別的配置項可以在詳細文檔中查看。
有關 electron-vue 的使用的更詳細的說明請看 中文文檔。
自動更新
安裝依賴
自動更新功能的實現依賴 electron-builder 和 electron-updater。
因為我們是用的electron-builder腳手架生成的項目,已經有 electron-builder 依賴了,所以只需要安裝 electron-updater。
# 目錄 E:\GitHub\autoupdateteset npm i electron-updater --save # 必須安裝為運行依賴,否則運行會出錯
配置 package.json
為了配合打包 package.json 需要給 build 新增配置項:
"build": {
"publish": [
{
"provider": "generic",
"url": "http://127.0.0.1:5500/" #這里是我本地開的服務器的地址
}
],
...
}
主進程(參考:electron 中文文檔)
主進程的入口文件是 src/main/index.js。
import {
app, // app 模塊是為了控制整個應用的生命周期設計的。
BrowserWindow, // BrowserWindow 類讓你有創(chuàng)建一個瀏覽器窗口的權力。
ipcMain
} from 'electron';
// 引入自動更新模塊
const { autoUpdater } = require('electron-updater');
// 不支持 ES6 則用如下方式引入
// const autoUpdater = require("electron-updater").autoUpdater
const feedUrl = `http://127.0.0.1:5500/win32`; // 更新包位置
/**
* 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, webContents;
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);
webContents = mainWindow.webContents;
mainWindow.on('closed', () => {
mainWindow = null;
});
}
// 主進程監(jiān)聽渲染進程傳來的信息
ipcMain.on('update', (e, arg) => {
console.log("update");
checkForUpdates();
});
let checkForUpdates = () => {
// 配置安裝包遠端服務器
autoUpdater.setFeedURL(feedUrl);
// 下面是自動更新的整個生命周期所發(fā)生的事件
autoUpdater.on('error', function(message) {
sendUpdateMessage('error', message);
});
autoUpdater.on('checking-for-update', function(message) {
sendUpdateMessage('checking-for-update', message);
});
autoUpdater.on('update-available', function(message) {
sendUpdateMessage('update-available', message);
});
autoUpdater.on('update-not-available', function(message) {
sendUpdateMessage('update-not-available', message);
});
// 更新下載進度事件
autoUpdater.on('download-progress', function(progressObj) {
sendUpdateMessage('downloadProgress', progressObj);
});
// 更新下載完成事件
autoUpdater.on('update-downloaded', function(event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
sendUpdateMessage('isUpdateNow');
ipcMain.on('updateNow', (e, arg) => {
autoUpdater.quitAndInstall();
});
});
//執(zhí)行自動更新檢查
autoUpdater.checkForUpdates();
};
// 主進程主動發(fā)送消息給渲染進程函數
function sendUpdateMessage(message, data) {
console.log({ message, data });
webContents.send('message', { message, data });
}
app.on('ready', () => {
createWindow();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
渲染進程
渲染進程的入口文件是 src/renderer/index.js。
這里我們主要修改 App.vue,將原來的內容全刪掉并使更新的整個周期在界面上打印出來。
<template>
<div id="app">
<!-- <router-view></router-view> -->
<button @click="autoUpdate()">獲取更新</button>
<ol id="content">
<li>生命周期過程展示</li>
</ol>
</div>
</template>
<script>
// import { ipcRenderer } from 'electron';
const { ipcRenderer } = require('electron');
export default {
name: 'my-project1',
mounted() {
var _ol = document.getElementById("content");
ipcRenderer.on('message',(event,{message,data}) => {
let _li = document.createElement("li");
_li.innerHTML = message + " <br>data:" + JSON.stringify(data) +"<hr>";
_ol.appendChild(_li);
if (message === 'isUpdateNow') {
if (confirm('是否現在更新?')) {
ipcRenderer.send('updateNow');
}
}
});
},
methods: {
autoUpdate() {
ipcRenderer.send('update');
}
}
};
</script>
<style>
/* CSS */
</style>
顯示的界面如下:

自動更新過程簡單介紹
1.將 webpack.json 里的版本號先改為 0.0.1,然后npm run build生成一個版本為0.0.1的安裝包。

注意上面一步會生成一個latest.yml文件,autoUpdate 實際上通過檢查該文件中安裝包版本號與當前應用版本號對比來進行更新判斷的。
latest.yml文件內容如下:

2.然后將上一步生成的安裝包放在本地開啟的服務器文件夾下,對應你在主程序入口文件中配置的服務器位置。

3.將 package.json 中的版本號改回0.0.0,再npm run build一遍,運行 build 文件夾下的 exe 安裝包,就將軟件安裝在你電腦里面了。點擊安裝完成后桌面上的快捷方式,再次點擊上面的獲取更新的按鈕就可以看到顯示在界面的自動更新生命周期了。(但這里因為會給你直接自動更新,所以會一閃而過,你可以在 autoUpdate 的各個生命周期事件里設置主進程與渲染進程通信,則可以一步一步觀察到整個自動更新的生命周期了。)
通過測試總結 autoUpdate 生命周期圖

更新過程展示
1、無版本更新

2、有版本更新
點擊取消后會先不更新,在應用關閉后更新:
點擊確認后則會直接更新:

踩過的坑
1、主進程與渲染進程通信
最開始我是直接在主進程直接運行更新
然后想在渲染進程中打印主進程傳過來的消息,但是發(fā)現只有 isUpdateNow 事件運行時才有日志顯示。
結果發(fā)現原來主進程與渲染進程之間通信必須在渲染進程已經運行的時候(即那個界面完全顯示出來)才能夠進行。所以我將自動更新改為界面按鈕觸發(fā),這樣才能檢測到自動更新的整個流程。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
fw.qq.com/ipaddress已失效 javascript獲得客戶端IP的新方法
一直以來,我都是通過http://fw.qq.com/ipaddress來獲得客戶端用戶的IP,這個方法簡單、快速、實用2012-01-01

