在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新

在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新

笔记贴:突然要用,每次都忘,记录下过程。没有使用
electron-packager打包的原因是测试过打包后体积上100M太大,暂时放弃。

1. 确认基础环境 及 electron文件夹结构

node -v
v10.16.3

electron -v
v6.0.9

npm -v
6.9.0

文件夹结构 单package.json结构 ,因参考官方文档显示:

Since version 8 electron-builder rebuilds only production dependencies, so, you are not forced to use two package.json structure.

二个文件夹说明

  1. app存放electron源码等
  2. builds存放打包后的输出target
    在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第1张图片

2. 修改文件

2.1. package.json

修改如下 注释需手动自己删掉才可运行:

{
 "name": "appTest",
 "version": "1.0.1",
 "main": "main.js",
 "author":"human",
 "scripts": {
  "start": "electron .",
  "builder": "electron-builder"
 },
 "build": {
   "appId": "com.ideal.app",
   "productName": "一个测试",
   "copyright" :"Copyright © 2019 ${author}",
   "asar": false, //asar 是否生成取决于配置项"asar": false不生成asar文件, 需要的话改为true
   "compression":"store",

   "directories": {
   "output": "../builds" //输出打包文件的目录
  },
  "publish": [
   {
    "provider": "generic",
    "url": "http://127.0.0.1:8080"  //更新服务器地址
   }
  ],
  "win": {
   "icon": "./assets/favicon.ico",
   "target": [
    "nsis",
    "zip"
   ],
   "artifactName": "${productName}_setup_${version}.${ext}",
   "timeStampServer": "http://timestamp.digicert.com"
  },
  "nsis": {
   "oneClick": false,
   "perMachine": true,
   "allowToChangeInstallationDirectory": true, //是否可以更改安装文件夹
   "allowElevation": true,
   "installerIcon": "favicon.ico",
   "installerSidebar":"./assets/installerSidebar164X314.bmp",
   "createDesktopShortcut": true,
   "runAfterFinish": true,
   "installerIcon": "./assets/favicon.ico",
   "uninstallerIcon": "./assets/favicon.ico",
    "license":"license.txt"
  }
 },
 "devDependencies": {
  "electron": "^6.0.9",
  "electron-builder": "^22.1.0"
 },
 "dependencies": {
  "electron-updater": "^4.2.0"
 }
}

2.2. main.js

const {app, BrowserWindow ,Tray ,Menu,ipcMain} = require('electron')

// 注意这个autoUpdater不是electron中的autoUpdater
const { autoUpdater } = require("electron-updater" )
const path = require('path')
// 一些自定义配置
const package = {
    version:"1.0.1",
    productEnv:"development",// development products
    feedUrl:'http://127.0.0.1:8080/'
};
const uploadUrl = 'http://127.0.0.1:8080/'
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

function updateHandle() {
  let message = {
    error: '检查更新出错',
    checking: '正在检查更新……',
    updateAva: '检测到新版本,正在下载……',
    updateNotAva: '现在使用的就是最新版本,不用更新',
  };
  const os = require('os');

  autoUpdater.setFeedURL(uploadUrl);
  autoUpdater.on('error', function (error) {
    console.log(error);
    sendUpdateMessage(message.error)
  });
  autoUpdater.on('checking-for-update', function () {
    console.log(message);

    sendUpdateMessage(message.checking)
  });
  autoUpdater.on('update-available', function (info) {
    console.log(message);

    sendUpdateMessage(message.updateAva)
  });
  autoUpdater.on('update-not-available', function (info) {
    sendUpdateMessage(message.updateNotAva)
  });

  // 更新下载进度事件
  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) => {
     //
      console.log("开始更新");
      //some code here to handle event
      autoUpdater.quitAndInstall();
    });

    mainWindow.webContents.send('isUpdateNow')
  });

  ipcMain.on("checkForUpdate",()=>{
      //执行自动更新检查
      autoUpdater.checkForUpdates();
  })
}

// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
  mainWindow.webContents.send('message', text)
}

function createWindow () {

  Menu.setApplicationMenu(null)
  //const appIcon = new Tray('icon.ico')
  
  mainWindow = new BrowserWindow({width:1000, height:800, title:'打包测试',icon: path.join(path.join(__dirname, 'assets'), 'favicon.ico'),webPreferences: {
     nodeIntegration: true
  }})
  
  mainWindow.loadURL(`file://${__dirname}/view/index.html`)

  mainWindow.on('closed', function () {
    mainWindow = null
  })
  if(package.productEnv == "development") mainWindow.webContents.openDevTools()  // 开启调试

    mainWindow.webContents.on('did-finish-load', () => { // 使用通信 版版本信息发送到渲染进程
        mainWindow.webContents.send('staticData', {"version":package.version});
    })
  updateHandle(); // 初始化更新相关监听

}

const gotTheLock = app.requestSingleInstanceLock()
 
if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // 当运行第二个实例时,将会聚焦到myWindow这个窗口
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()
    }
 })
 
app.on('ready', function(){
    createWindow();
    Menu.setApplicationMenu(null);// 屏蔽electron 默认菜单栏
})
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})
}

2.3 为测试修改下index.html

因入口文件定义为mainWindow.loadURL(file://${__dirname}/view/index.html)
index.html文件放在app/view/下

<!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8">
      <title>Hello World!</title>
    </head>
    <body>
      <h1>最新版本:v<span id="update-version"></span>!</h1>
自动更新
      <progress id="update-progress" value='0' max='100'></progress>
    </body>
  </html>

  <script crossorigin  sssrc="https://code.jquery.com/jquery-2.2.0.min.js"></script>
  <script>if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};</script>
<script>


const ipcRenderer = require('electron').ipcRenderer
var Upd_version   = document.getElementById("update-version");
var Upd_progress  = document.getElementById("update-progress");
var Upd_percent   = 0;


ipcRenderer.on("staticData",function(event,data){
    // 获取配置项数据
    console.log(data)

    if(data.version) {
        Upd_version.innerText = data.version;
        if(typeof window.updateVerson == 'function') _app.innerText = data.version;
    }
})
ipcRenderer.send("checkForUpdate");

ipcRenderer.on("message", (event, text) => {
            console.log(text);
            this.tips = text;
        });
ipcRenderer.on("downloadProgress", (event, progressObj)=> {
            console.log(progressObj);
            this.downloadPercent = progressObj.percent || 0;
             Upd_progress.value = Number(progressObj.percent);
            
        Upd_percent = Number(progressObj.percent);


        });


        ipcRenderer.on("isUpdateNow", () => {


            ipcRenderer.send("isUpdateNow");
        });
</script>

3. 打包

electron-builder官方文档多参考

在package.json中已经定义好了buider,
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第2张图片

npm run builder

运行效果:
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第3张图片
查看builds文件夹,看是否打包成功, 点击exe安装测试一遍,没有问题代表打包成功
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第4张图片
点击exe安装截图:
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第5张图片
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第6张图片
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第7张图片
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第8张图片
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第9张图片
桌面图标:
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第10张图片

4. electron-updater更新

4.1为测试方便再builds文件夹下建立一个app.js启动一个http服务器

// app.js
var express = require('express')
var fs = require('fs')
const path = require('path')
app.use(express.static(path.join(__dirname, './')))
var server = app.listen(8080, function () {
  var host = server.address().address;
  var port = server.address().port;
 
  console.log('Example app listening at http://%s:%s', host, port);
});

4.2 运行app.js

node app.js
Example app listening at http://:::8080

4.3 生成一个新版本号的打包程序

4.3.1 修改代码版本号

在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第11张图片
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第12张图片

4.3.2 打包

运行npm run builder
结束后查看文件夹
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第13张图片

4.3.3 运行启动1.0.1版本

检测到新版下载更新, 下载的临时文件存放路径:
查看builds文件夹下win-unpacked\resources\app-update.yml

provider: generic
url: 'http://127.0.0.1:8080'
updaterCacheDirName: apptest-updater

在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第14张图片

在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第15张图片
因为使用了本地服务器所以下载速度过快,效果:
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第16张图片

4.4 修改latest.yml中releaseDate为当地时间

输出的latest.yml中releaseDate总是显示: '2019-11-22T02:42:48.634Z’非当地时间戳,强迫症要调整一下,哈哈
先测试下node的时间输出:

> new Date().toISOString() //The time zone [offset] is always UTC, denoted by the suffix Z
'2019-11-22T02:42:48.634Z'
> new Date().toGMTString()
'Fri, 22 Nov 2019 02:44:25 GMT'
> new Date().toLocaleString()
'2019-11-22 10:44:31 AM'

找到electron-builder所用到的打包模块文件 修改时间为new Date().toLocaleString()
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第17张图片
修改后
在windows上 electron 利用electron-builder实现打包,配合electron-updater自动更新_第18张图片
输出的latest.yml中releaseDate为当地时间 : ‘2019-11-22 10:45:52 AM’

参考:https://blog.csdn.net/Wonder233/article/details/80563236
https://www.jianshu.com/p/15bde714e198

你可能感兴趣的:(Electron)