在上一篇文章中,我们介绍了electron的一些基础知识, 入门Electron,手把手教你编写完整实用案例,在这里我们将基于这个项目继续介绍Electron的打包和自动更新。
生成图标
在打包应用之前,要为应用准备一个图标,作为安装包图标。不同的操作系统所需图标的格式不同,Mac对应的格式为icns
,Windows对应的格式为ico
。
图标的生成可以借助 electron-icon-builder
。
- 首先,准备一张
1024*1024的png
图片,将图片放在项目文件夹中,我们这里选择放在tasky/public文件夹
中。
-
安装 electron-icon-builder:
npm i electron-icon-builder --D
-
在
package.json
的scripts
添加指令:"build-icon": "electron-icon-builder --input=./public/icon.png --output=build --flatten"
-
运行
npm run build-icon
,就会在build
文件夹中生成一系列打包所需的图标文件。
打包应用
Electron生态下常用的打包工具有两个:electron-builder
和 electron-packager
。
electron-builder
配置更灵活,使用也更广泛。下面,我们使用electron-builder
来进行打包。
安装
npm i electron-builder --D
配置
使用electron-builder
打包主要是各种配置,它支持两种配置方式:
- 在
package.json
中添加build
字段:
"build": {
"appId": "your.app.id"
}
- 指定配置文件,在其中写入配置项。默认是项目根目录下的electron-builder.yml。
appId:"your.app.id"
在日常开发中,package.json
这种配置方式比较常用,我们也以这种方式为主。
基础配置
"build": {
"appId": "this.is.tasky",
"productName": "Tasky",
"copyright": "Copyright © 2021 Alaso",
"directories": {
"buildResources": "build", //指定打包需要的静态资源,默认是build
"output": "dist", //打包生成的目录,默认是dist
}
},
build文件夹放置的是,electron-builder
默认的在打包过程中需要的静态文件,比如我们上面生成的图标文件;dist文件夹放置的是打包生成的各种文件。
- 在
package.json
的scripts
添加指令:"pack": "electron-builder"
- 运行
npm run pack
基于以上的配置,electron-builder
会根据当前的操作系统打包出默认的文件。比如,在windows平台下,打包结果如下:
平台相关的配置
electron-builder
会自动识别当前的操作系统,打出系统对应的安装包。 这也意味着,如果要生成exe\msi,需要在Windows操作系统,如果是dmg,则需要在Mac操作系统。
electron-builder
的配置选项中,有很多跟操作系统相关的配置,可以对不同平台的打包做一些定制效果。下面以Windows和Mac为例,介绍一些常用的平台相关的配置。
- Windows
"build": {
...
"win": {
"target": ["msi","nsis"], //安装包的格式,默认是"nsis"
"icon": "build/icons/icon.ico" //安装包的图标
},
//"target"值"nsis"打包出来的就是exe文件
//nsis是windows系统安装包的制作程序,它提供了安装、卸载、系统设置等功能
//关于"nsis"的一些配置
"nsis": {
"oneClick": false, //是否一键安装,默认为true
"language": "2052", //安装语言,2052对应中文
"perMachine": true, //为当前系统的所有用户安装该应用程序
"allowToChangeInstallationDirectory": true //允许用户选择安装目录
}
}
2. Mac
...
"build": {
"mac": {
"target": ["dmg", "zip"], //安装包的格式,默认是"dmg"和"zip"
"category": "public.app-category.utilities" //应用程序安装到哪个分类下,具体有哪些分类可以在苹果官网上找
},
"dmg": {
"background": "build/background.jfif", //安装窗口背景图
"icon": "build/icons/icon.icns", //安装图标
"iconSize": 100, //图标的尺寸
"contents": [ //安装图标在安装窗口中的坐标信息
{
"x": 380,
"y": 180,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 180,
"type": "file"
}
],
"window": { //安装窗口的大小
"width": 540,
"height": 380
}
}
}
会将哪些文件pack到安装包
在打包生成的文件夹中,会有一个app.asar
,它是Electron应用程序的主业务文件压缩包,要知道项目中哪些文件被pack到安装包,可以通过解压app.asar
进行查看。
解压app.asar
需要借助asar工具,首先来安装:npm i asar -g
。
然后切换到app.asar
所在目录,执行:asar extract app.asar ./app-folder
。
以windows为例,app.asar
位于tasky\dist\win-unpacked\resources
目录中,解压后,可以看到app-folder中的内容如下:
可以看到,基本上就是项目所有文件了(除了package-lock.json
\ .gitignore
\ build
文件夹),并且还有node_modules
。
对于node_modules
,并不是所有node_modules
中的内容都会被打包进安装包,只有package.json
中dependencies
字段中的依赖会被打包,devDependencies
字段中的依赖则不会。 这是唯一规则,跟项目实际是否使用依赖没有关系。
所以,为了减小安装包体积,建议在渲染进程中使用的外部包,都安装在devDependencies
中,然后使用webpack将外部包的代码和业务代码打包到一起,在后面的文章中会详细介绍。
当然,可以通过配置files字段,来指定将哪些内容进行打包。
比如,我们只打包src文件夹
、index.js
和package.json
,可以这样配置:
"build": {
"files": [
"package.json",
"index.js",
"src/**/*"
]
}
自动更新
要自动更新,应用程序的安装包应该存放在互联网的某台服务器上,每次打开应用的时候,进行自动检测,根据当前应用程序的version
和线上版本进行匹配,当发现有新的version
的时候,就自动下载,下载完成后,询问用户是否安装新版本。
打包不同版本
在package.json
中,有个"version"
字段,用于决定当前版本。
- step1: 设置
"version": "1.0.0"
,运行npm run pack
- step2: 设置
"version": "1.0.1"
, 运行npm run pack
虽然,我们没有改变应用程序的内容,但是会被识别成"1.0.0"和"1.0.1"两个版本。
搭建一个服务器放安装包
我们在本地启动一个服务器,放最新版本的安装包资源。
- 1、初始化
mkdir tasky-server
cd tasky-server
npm init -y
npm install koa koa-static --save
- 2、在tasky-server目录下新建
index.js
,内容如下:
const Koa = require('koa')
const app = new Koa()
const static = require('koa-static')
const path = require('path')
app.use(static(path.join(__dirname,'./static')));
app.listen(9005)
- 3、在创建一个
static
文件夹,放入最新版本的安装包set。具体包含哪些文件呢?假如最新版本是"1.0.1"。
Mac平台: latest-mac.yml
、 Tasky-1.0.1-mac.zip
、Tasky-1.0.1.dmg
、Tasky-1.0.1.dmg.blockmap
Windows平台: latest.yml
、Tasky 1.0.1.msi
、Tasky Setup 1.0.1.exe
、Tasky Setup 1.0.1.exe.blockmap
- 4、启动服务器。
node index.js
检测更新
检测更新可以借助electron-updater
来实现。它结合electron-builder
,实现起来非常简单。直接上代码。
- 第一步、在build中配置
"publish"
字段:
"build": {
...
"publish": [
{
"provider": "generic",
"url": "http://127.0.0.1:9005/"
}
]
}
第二步、在应用程序主进程中调用electron-updater
模块检测更新。
const { autoUpdater } = require('electron-updater')
function checkUpdate(){
if(process.platform == 'darwin'){
//我们使用koa-static将静态目录设置成了static文件夹,
//所以访问http://127.0.0.1:9005/darwin,就相当于访问了static/darwin文件夹,win32同理
autoUpdater.setFeedURL('http://127.0.0.1:9005/darwin') //设置要检测更新的路径
}else{
autoUpdater.setFeedURL('http://127.0.0.1:9005/win32')
}
//检测更新
autoUpdater.checkForUpdates()
//监听'error'事件
autoUpdater.on('error', (err) => {
console.log(err)
})
//监听'update-available'事件,发现有新版本时触发
autoUpdater.on('update-available', () => {
console.log('found new version')
})
//默认会自动下载新版本,如果不想自动下载,设置autoUpdater.autoDownload = false
//监听'update-downloaded'事件,新版本下载完成时触发
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({
type: 'info',
title: '应用更新',
message: '发现新版本,是否更新?',
buttons: ['是', '否']
}).then((buttonIndex) => {
if(buttonIndex.response == 0) { //选择是,则退出程序,安装新版本
autoUpdater.quitAndInstall()
app.quit()
}
})
})
}
app.on('ready', () => {
//每次启动程序,就检查更新
checkUpdate()
}
是否需要更新是根据什么判断的呢?
electron-updater会根据上面setFeedURL指定路径下的latest.yml
中的version
来判断是否需要更新,大于当前版本的version
则需要更新,否则不更新。.yml
也是一种配置文件,有点类似于我们常用的.json
配置文件,两者写法不一样。
基于github的方案
如果你不想搭建自己的服务器,也可以借助github。使用github自动发布,不用每次手动上传最新安装包资源。
自动发布
第一步,依然是配置"publish"
字段。
"build": {
...
"publish": ['github']
}
第二步、在"scripts"
中配置新的指令,由于github权限控制,需要GH_TOKEN,可以在 https://github.com/settings/tokens 中生成GH_TOKEN。
"scripts": {
...
"release": "cross-env GH_TOKEN=ghp_KmVD3.......W2k3Pd4vV electron-builder"
}
第三步、npm run release
,就会在打包后,将资源上传到github,生成release draft,你在github项目中,找到这个draft,publish release就可以了。
检测更新
和上面类似,以Windows为例,代码如下。
const { autoUpdater } = require('electron-updater')
function checkUpdate(){
//检测更新
autoUpdater.checkForUpdates()
//监听'error'事件
autoUpdater.on('error', (err) => {
console.log(err)
})
//监听'update-available'事件,发现有新版本时触发
autoUpdater.on('update-available', () => {
console.log('found new version')
})
//默认会自动下载新版本,如果不想自动下载,设置autoUpdater.autoDownload = false
//监听'update-downloaded'事件,新版本下载完成时触发
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({
type: 'info',
title: '应用更新',
message: '发现新版本,是否更新?',
buttons: ['是', '否']
}).then((buttonIndex) => {
if(buttonIndex.response == 0) { //选择是,则退出程序,安装新版本
autoUpdater.quitAndInstall()
app.quit()
}
})
})
}
app.on('ready', () => {
//每次启动程序,就检查更新
checkUpdate()
}
结语
我们上面的例子中,是将页面的web资源都打包到了安装包,还有一种情况就是,web资源和“app壳子”分离,web资源放在服务器,每次都通过网络动态加载,像下面这样:
mainWindow.loadURL('https://juejin.cn')
在业务需要频繁更新的场景中,可以使用这种方式,快速无障碍地实现更新。在这种情况下,我们可以按照上述方式打包和更新“壳子”,也就是主进程相关;而页面资源的打包和普通的前端项目打包无异,这里不再赘述。
这篇文章主要讲解了使用electron-builder
打包应用和自动更新,在下一篇文章中,我们将探讨Electron和Vue的结合使用。
原文地址:https://juejin.cn/post/6980105328801087518