说明:
本文的自动更新功能使用的项目为 electron-vue 脚手架搭建一个默认项目。
参考的文章如下:
开始:新建一个 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 # 压缩及运行环境的配置文件 |- build # |- icons # 图标文件 |- ... # 打包生成的文件在此处 |- dist # 用 webpack 压缩项目后生成的压缩文件在此处 |- node_modules |- src # 资源文件 |- main # 主进程 |- renderer # 渲染进程 |- index.ejx # 入口文件 |- static # 静态资源 |- .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 会有的:
下面重点看后面的内容:electron-builder详细配置文档
有关 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 类让你有创建一个浏览器窗口的权力。 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; }); } // 主进程监听渲染进程传来的信息 ipcMain.on('update', (e, arg) => { console.log("update"); checkForUpdates(); }); let checkForUpdates = () => { // 配置安装包远端服务器 autoUpdater.setFeedURL(feedUrl); // 下面是自动更新的整个生命周期所发生的事件 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(); }); }); //执行自动更新检查 autoUpdater.checkForUpdates(); }; // 主进程主动发送消息给渲染进程函数 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、主进程与渲染进程通信
最开始我是直接在主进程直接运行更新
然后想在渲染进程中打印主进程传过来的消息,但是发现只有 isUpdateNow 事件运行时才有日志显示。
结果发现原来主进程与渲染进程之间通信必须在渲染进程已经运行的时候(即那个界面完全显示出来)才能够进行。所以我将自动更新改为界面按钮触发,这样才能检测到自动更新的整个流程。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
所有 electron-builder 生成的文件都可以在 build 文件夹中找到。 构建 npm run build 构建未打包的目录 生成简单的可执行文件,没有完整的安装程序。用于快速测试。 npm run build:dir 默认的构建配置 可以在 package.json 中使用基于 electron-builder 的 各种选项 进行进一步定制。 "build": { "produc
Vue CLI Plugin Electron Builder Easily Build Your Vue.js App For Desktop With Electron Build status: Top Supporters Glenn Frank Quick Start: Open a terminal in the directory of your app created with V
electron-builder的allowElevation和requestedExecutionLevel设置为管理员权限没作用有人知道什么问题吗?打出来的包requestedExecutionLevel我看了下还是asInvoker
在使用electron 测试demo的时候, 想要引入electron的app, 但是在打印的时候,却是undefined. npx tsx test/test.ts 执行打印: test/test.ts 1、上面引入的join方法都可以打印。为何electron的app是undefined呢? 2、还是说electron的内置只能在src/main/ 主进程目录下执行呢? 3、如果只能在主进程目
Electron获取package.json文件中定义的主文件并执行它。 此主文件创建应用程序窗口,其中包含呈现的网页以及与操作系统的本机GUI(图形用户界面)的交互。 当您使用Electron启动应用程序时,会创建一个main process 。 该主要过程负责与操作系统的本机GUI交互。 它创建了应用程序的GUI。 刚启动主进程并不会为应用程序的用户提供任何应用程序窗口。 这些是由主文件中的主
问题内容: 使用此样板作为参考,我创建了一个Electron应用程序。它使用webpack捆绑脚本并通过Express Server托管脚本。 的WebPack配置是实质上相同的这个和服务器这样。 Electron的脚本加载: 然后index.html加载服务器托管的脚本: 我运行以构建应用程序并启动服务器,该服务器使用webpack将脚本捆绑在一起。 它工作正常,我的React组件App已安装。