由于8月份上旬公司开发一款桌面应用程序,在前端开发程序打包更新时遇到一些困扰多日的问题,采用electron-builder最终还是得到解决~

以下是踩坑的过程及对electron打包与更新思路的梳理,electron打包与更新的正确姿势应该如下图所示

下面将逐一展开描述说明

    一、windows系统下环境配置

NPM是随NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题

  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

在windows平台系统下,使用cmd命令设置npm安装模块、electron打包所需环境

npm config set prefix "C:\Program Files (x86)\nodejs\npm_global" 设置全局模块安装路径
npm config set cache "C:\Program Files (x86)\nodejs\npm_cache" 设置缓存文件夹
npm config set registry "https://registry.npm.taobao.org" 设置淘宝镜像
electron npm config set electron_mirror "https://npm.taobao.org/mirrors/electron/" electron可以通过设置淘宝镜像快速下载
npm config set arch ia32
npm config set target_arch ia32
npm config set disturl https://npm.taobao.org/mirrors/atom-shell
npm config set runtime electron
npm config set build_from_source true

    二、打包成可执行的运行包

electron-quick-start中,配置文件package.json中添加一句,通过npm包管理器npm install依赖模块与 npm install electron-packager --save

"scripts": {
"package": "electron-packager ./ --overwrite -all"
}

执行npm run package 命令,即可得到可执行运行包,可运行包内部大致说明如下图

由于"../electron-quick-start/electron-quick-start-win32-ia32/resources/app"路径下开发项目代码资源是裸露的,出于安全性和代码保护性考虑

所以需要asar对开发项目资源进行二进制加密,asar加密文件可读不可写.

    三、将打包成可执行的运行包进行asar二进制加密

安装  npm install --save-dev asar 
安装完成以后,就可以使用asar命令将裸露程序文件打包了 asar pack ./app app.asar 
后将app文件移除掉即可

    四、使用NSIS将可执行的运行包打成安装包

在windows系统下采用NSIS将打包成可安装程序

下载前至NSIS 3.0 .1正式版汉化增强版

使用VNISEdit 编译环境具体教程请参考win7下nsis打包exe安装程序教程

生成脚本

 ; 该脚本使用 HM VNISEdit 脚本编辑器向导产生

 ; 安装程序初始定义常量
!define PRODUCT_NAME "My application"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_PUBLISHER "My company, Inc."
!define PRODUCT_WEB_SITE "http://www.mycompany.com"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\electron-quick-start.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM" SetCompressor lzma ; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------
!include "MUI.nsh" ; MUI 预定义常量
!define MUI_ABORTWARNING
!define MUI_ICON "app.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" ; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 许可协议页面
!insertmacro MUI_PAGE_LICENSE "..\YourSoftwareLicence.txt"
; 安装目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面
!define MUI_FINISHPAGE_RUN "$INSTDIR\electron-quick-start.exe"
!insertmacro MUI_PAGE_FINISH ; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES ; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "SimpChinese" ; 安装预释放文件
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------ Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Setup.exe"
InstallDir "$PROGRAMFILES\My application"
InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
ShowInstDetails show
ShowUnInstDetails show Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File /r "*.*"
CreateDirectory "$SMPROGRAMS\My application"
CreateShortCut "$SMPROGRAMS\My application\My application.lnk" "$INSTDIR\electron-quick-start.exe"
CreateShortCut "$DESKTOP\My application.lnk" "$INSTDIR\electron-quick-start.exe"
File "electron-quick-start.exe"
SectionEnd Section -AdditionalIcons
WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
CreateShortCut "$SMPROGRAMS\My application\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
CreateShortCut "$SMPROGRAMS\My application\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd Section -Post
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\electron-quick-start.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\electron-quick-start.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd /******************************
* 以下是安装程序的卸载部分 *
******************************/ Section Uninstall
Delete "$INSTDIR\${PRODUCT_NAME}.url"
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\electron-quick-start.exe" Delete "$SMPROGRAMS\My application\Uninstall.lnk"
Delete "$SMPROGRAMS\My application\Website.lnk"
Delete "$DESKTOP\My application.lnk"
Delete "$SMPROGRAMS\My application\My application.lnk" RMDir "$SMPROGRAMS\My application" RMDir /r "$INSTDIR\resources"
RMDir /r "$INSTDIR\locales" RMDir "$INSTDIR" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
SectionEnd #-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--# Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) ,及其所有的组件?" IDYES +2
Abort
FunctionEnd Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。"
FunctionEnd

    五、windows系统安装程序更新

安装npm install  electron-updater 在应用中触发更新检查, electron-updater 自动会通过对应url下的yml文件检查更新

在入口文件main.js中需注意

 //if you don't use ES6: const autoUpdater = require("electron-updater").autoUpdater
const autoUpdater = require('electron-updater').autoUpdater
//ipcMain 主线程
const ipcMain = require('electron').ipcMain

autoUpdater

 // 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
function updateHandle(){
//minimize
ipcMain.on('hide-window', () => {
mainWindow.minimize();
});
//maximize
ipcMain.on('show-window', () => {
mainWindow.maximize();
});
//unmaximize
ipcMain.on('orignal-window', () => {
mainWindow.unmaximize();
});
//打开默认浏览器
ipcMain.on('open-office-website', function(event, arg){
shell.openExternal(arg)
}) ipcMain.on('check-for-update', function(event, arg) {
let message={
appName:'智卡桌面应用讨论',
error:'检查更新出错, 请联系开发人员',
checking:'正在检查更新……',
updateAva:'检测到新版本,正在下载……',
updateNotAva:'现在使用的就是最新版本,不用更新',
downloaded: '最新版本已下载,将在重启程序后更新'
};
//设置检查更新的 url,并且初始化自动更新。这个 url 一旦设置就无法更改。
const updateFeedUrl='http://www.baidu.com/updates/latest/win/';
if(os.platform()==='darwin'){
updateFeedUrl='http://www.baidu.com/updates/latest/mac/';
}
autoUpdater.setFeedURL(updateFeedUrl); autoUpdater.on('error', function(error){
return dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['OK'],
title: message.appName,
message: message.errorTips,
detail: '\r' + message.error
}); sendUpdateMessage(message.error)
}); //当开始检查更新的时候触发
autoUpdater.on('checking-for-update', function() {
sendUpdateMessage(message.checking)
return dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['OK'],
title: message.appName,
message: message.checking
});
}); //当发现一个可用更新的时候触发,更新包下载会自动开始
autoUpdater.on('update-available', function(info) {
sendUpdateMessage(message.updateAva)
var downloadConfirmation = dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['OK'],
title: message.appName,
message: message.updateAva
});
if (downloadConfirmation === 0) {
return;
}
}); //当没有可用更新的时候触发
autoUpdater.on('update-not-available', function(info) {
return dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['OK'],
title: message.appName,
message: message.updateNotAva
});
sendUpdateMessage(message.updateNotAva)
}); // 更新下载进度事件
autoUpdater.on('download-progress', function(progressObj) {
mainWindow.webContents.send('downloadProgress', progressObj)
})
/**
* event Event
* releaseNotes String - 新版本更新公告
* releaseName String - 新的版本号
* releaseDate Date - 新版本发布的日期
* updateURL String - 更新地址
* */
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
var index = dialog.showMessageBox(mainWindow, {
type: 'info',
buttons: ['现在重启', '稍后重启'],
title: message.appName,
message: message.downloaded,
//detail: releaseName + "\n\n" + releaseNotes
});
console.log(index);
if (index === 1) return;
//在下载完成后,重启当前的应用并且安装更新
autoUpdater.quitAndInstall();
//通过main进程发送事件给renderer进程,提示更新信息
//mainWindow.webContents.send('isUpdateNow')
}); //执行自动更新检查
autoUpdater.checkForUpdates();
});
}

Squirrel.Windows 是windows系统下electron-updater 检查更新lib库

关于Squirrel.Windows 更详细说明,请连接至 https://github.com/Squirrel/Squirrel.Windows

Squirrel is both a set of tools and a library, to completely manage both installation and updating your Desktop Windows application, 
written in either C# or any other language (i.e., Squirrel can manage native C++ applications).  

    六、主线程与渲染线程之间通信

点击更新按钮后

 //检查更新
$("#accLogin").find(".T-updateApp").on("click", function() {
setTimeout(function() {
//update 渲染进程
ipcr.send('check-for-update', 'event-update');
}, 20);
});

触发主线程(上述步骤五 updateHandle 方法中) ipcMain.on('check-for-update', function(event, arg) { //执行操作 }) 检查更新 autoUpdater各种状态

ipcMain.on('check-for-update', function(event, arg) {
//设置检查更新的 url,并且初始化自动更新。这个 url 一旦设置就无法更改。
const updateFeedUrl='http://www.baidu.com/updates/latest/win/';
if(os.platform()==='darwin'){
updateFeedUrl='http://www.baidu.com/updates/latest/mac/';
}
autoUpdater.setFeedURL(updateFeedUrl); autoUpdater.on('error', function(error){}); //当开始检查更新的时候触发
autoUpdater.on('checking-for-update', function() {}); //当发现一个可用更新的时候触发,更新包下载会自动开始
autoUpdater.on('update-available', function(info) {}); //当没有可用更新的时候触发
autoUpdater.on('update-not-available', function(info) {}); // 更新下载进度事件
autoUpdater.on('download-progress', function(progressObj) {})
/**
* event Event
* releaseNotes String - 新版本更新公告
* releaseName String - 新的版本号
* releaseDate Date - 新版本发布的日期
* updateURL String - 更新地址
* */
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {}); //执行自动更新检查
autoUpdater.checkForUpdates();
});

    七、electron-builder 解决方案(项目打包、运行包、安装包、更新、支持多平台)

A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box

(大致意思 electron-builder一个完整的解决方案,打包和建立一个分发的electron程序与“auto update”支持开箱即用)

通过以上六点知识总结,不难理解electron-builder,这里附一package.json配置文件,后面博主将抽时间写一篇关于electron-builder打包、更新更详细文章

{
"name": "electron-build",
"version": "1.6.13",
"main": "src/main.js",
"description": "electron-build project",
"author": "Avenstar",
"license": "",
"devDependencies": {
"electron": "^1.4.15",
"electron-builder": "^12.3.1"
},
"dependencies": {
"electron-updater": "^1.4.2"
},
"scripts": {
"pack": "electron-builder --dir",
"build": "electron-builder",
"dev": "electron src/main.js"
},
"keywords": [
"electron",
"updater",
"update",
"mac",
"osx",
"linux",
"desktop"
],
"build": {
"appId": "com.cilent.app.electronbuild",
"productName": "electron-build",
"directories": {
"output": "build"
},
"files": [
"src/**/*",
"node_modules/**/*",
"package.json"
],
"dmg": {
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"category": "your.app.category.type",
"icon": "static/icons/app.icns",
"target": [
"zip",
"dmg"
],
"publish": [
{
"provider":"generic",
"url":"http://www.baidu.com/updates/latest/mac/"
}
]
},
"win": {
"icon": "static/icons/icon.ico",
"target": [
"nsis",
"zip"
],
"publish": [
{
"provider":"generic",
"url":"http://www.baidu.com/updates/latest/win/"
}
]
},
"linux": {
"icon": "static/icons"
},
"nsis":{
"oneClick":true,
"artifactName":"${productName}-setup-${version}.${ext}"
}
}
}

作者:Avenstar

出处:http://www.cnblogs.com/zjf-1992/p/7354931.html

关于作者:专注于前端开发

本文版权归作者所有,转载请标明原文链接

资料参考

https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating

https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating

https://changkun.us/archives/2017/03/217/?utm_source=tuicool&utm_medium=referral

https://github.com/amhoho/electron-cn-docs

https://segmentfault.com/a/1190000010271226

https://segmentfault.com/a/1190000004863646

https://github.com/electron-userland/electron-builder

https://github.com/Squirrel/Squirrel.Windows

https://segmentfault.com/a/1190000008287730

最新文章

  1. 关于json序列化循环引用导致出错
  2. ubuntu sudo update与upgrade的作用及区别
  3. DEM数据如何生成高程点
  4. Python私有变量
  5. 知识管理(knowledge Management)2
  6. 【Demo 0007】Android 信使(Intent)
  7. MFC中获取系统当前时间
  8. eclipse安装git插件
  9. MySQL数据库引擎介绍、区别
  10. 试着把.net的GC讲清楚(3)
  11. 苹果电脑利用curl下载数据集
  12. Python中操作Redis
  13. [02] Spring主要功能模块概述
  14. caffe solver 配置详解
  15. DataGrip 连接数据库查询出来的结果乱码的问题
  16. java NIO Buffer 详解(1)
  17. git常用命令二
  18. Network In Network——卷积神经网络的革新
  19. second scrum meeting - 151026
  20. ECMAScript6教程目录

热门文章

  1. CSS3学习系列之动画
  2. Angular路由(三)
  3. .net 实现aop的三种方法。
  4. Watson Explorer Analytical Components 2
  5. JavaWeb 后端 <一> 之 Tomcat服务器 - Http协议 学习笔记
  6. voa 2015 / 4 / 19
  7. Tomcat服务器无法启动socket监听端口
  8. 输入三个整数x、y、z,请把这三个数由小到大输出
  9. MySQL 启动参数说明及性能优化建议
  10. python中的判断语句与循环语句