electron-build与electron-update实现自动更新

·  阅读 2943

一、前言

  • NW.jsElectron 都可以用前端的知识来开发桌面应用。NW.jsElectron起初是同一 个作者开发。后来种种原因分为两个产品。一个命名为 NW.js(英特尔公司提供技术支持)、 另一命名为Electron(Github 公司提供技术支持)。

  • NW.jsElectron 可以用Nodejs 中几乎所有的模块NW.jsElectron不仅可以把html 写的 web 页面打包成跨平台可以安装到电脑上面的软件,也可以通过 javascript 访问操作 系统原生的 UI 和 Api(控制窗口、添加菜单项目、托盘应用菜单、读写文件、访问剪贴板)。

1.1 Electron 是由谁开发的?

Electron 是由 Github 开发

1.2 Electron 是什么?

Electron 是一个用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库

1.3 Electron 把 HTML,CSS 和 JavaScript 组合的程序构建为跨平台桌面应用程序的原理 是什么?

原理为 Electron 通过将 Chromium 和 Node.js 合并到同一个运行时环境中,并将其打包为 Mac,Windows 和 Linux 系统下的应用来实现这一目的。

二、electron-vue

作为前端,本身需要学的东西就很多。所以这里直接使用 electron-vue来构建桌面应用。

electron-vue 中文文档

electron-vue Github地址

electron-vue 环境搭建、创建项目

这里推荐yarn,至于为什么,官网是这么推荐的。而且在安装依赖时,速度也是很快

vue init simulatedgreg/electron-vue my-project

cd my-project

yarn

yarn run dev

electron-vue 中隐藏顶部菜单隐藏

electron-vue 中隐藏顶部菜单隐藏顶部最大化、最小化、关闭按钮 自定最大化、最小化 、关闭按钮

electron-vue 中隐藏顶部菜单

// src/main/index.js
mainWindow.setMenu(null)

electron-vue 中隐藏关闭 最大化 最小化按钮

// src/main/index.js
mainWindow = new BrowserWindow({
    height: 620,
    useContentSize: true,
    width: 1280,
    frame: false /*去掉顶部导航 去掉关闭按钮 最大化最小化按钮*/
})

electron-vue 自定义关闭/最大化最小化按钮

// 注意在mac下不需要监听窗口最大最小化、以为系统默认支持,这个只是针对windows平台

ipc.on('window-min',function() {
    mainWindow.minimize();
})

//登录窗口最大化 
ipc.on('window-max',function(){
    if (mainWindow.isMaximized()) {
        mainWindow.restore();
    } else {
        mainWindow.maximize();
    }
}) 

ipc.on('window-close',function() {
    mainWindow.close();
})

electron-vue 自定义导航可拖拽

  • 可拖拽的 css: -webkit-app-region: drag;
  • 不可拖拽的 css: -webkit-app-region: no-drag;

electron-update 实现手动/自动更新

话不多说,直接上代码。。。

// package.json
"build": {
...
    "publish": {
        "provider": "generic", // 这个意思是,使用自己的文件服务器
        "url": "http:..." // 文件服务器的地址
    }
...
}

文件服务器的构建,根据自己的实际情况使用技术栈。 我是使用nginx搭建了一个文件服务器,具体代码就不贴出来了,比较简单

// src/main/index.js
'use strict'

import { app, BrowserWindow, ipcMain, globalShortcut } from 'electron'
import { autoUpdater } from 'electron-updater'
const uploadUrl = '文件服务器地址'

/*
 * 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
const winURL = process.env.NODE_ENV === 'development'
  ? `http://localhost:9080`
  : `file://${__dirname}/index.html`

// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
function updateHandle () {
  let message = {
    error: { status: -1, message: '检查更新出错' },
    checking: { status: 1, message: '正在检查更新……' },
    updateAva: { status: 2, message: '检测到新版本,正在下载……' },
    updateNotAva: { status: 3, message: '已是最新版本,无需更新' }
  }
  // const os = require('os')

  autoUpdater.setFeedURL(uploadUrl)
  autoUpdater.on('error', function () {
    sendUpdateMessage(message.error)
  })
  autoUpdater.on('checking-for-update', function () {
    sendUpdateMessage(message.checking)
  })
  autoUpdater.on('update-available', function (info) {
    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(arguments)
    //   console.log('开始更新')
    // some code here to handle event
    autoUpdater.quitAndInstall()
    // })

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

  autoUpdater.checkForUpdates()
}

ipcMain.on('checkForUpdate', () => {
  updateHandle()
  // 执行自动更新检查
})

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

function createWindow () {
  /**
   * Initial window options
   */
  mainWindow = new BrowserWindow({
    height: 363,
    useContentSize: true,
    width: 600
  })

  mainWindow.loadURL(winURL)
  // let update = new Update(mainWindow)

  mainWindow.on('closed', () => {
    mainWindow = null
  })
  mainWindow.setMenu(null)
  // updateHandle()

  // 调试
  globalShortcut.register('CTRL+SHIFT+I', function () {
    mainWindow.webContents.openDevTools()
  })
}

app.on('ready', async () => {
  createWindow()
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})

视图层

这里使用了element-ui,根据自己的情况选取ui框架

// components/update
<template>
  <div class="com-update">
    <el-row type="flex" justify="end">
      <el-col :span="1" :xs="3" :md="2" :lg="1">
        <el-tag @click="showUpdater" size="mini" type="info" effect="plain">检查版本</el-tag>
      </el-col>
    </el-row>
    <el-dialog
      title="更新中,请稍等。。。"
      :visible="showDialog"
      width="30%"
      center
      :close-on-press-escape="false"
      :close-on-click-modal="false"
      :show-close="false"
    >
      <el-row type="flex" justify="center">
        <el-col :span="11">
          <el-progress type="circle" :percentage="process"></el-progress>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>

<script>
import { ipcRenderer } from 'electron'

export default {
  name: 'update',

  data() {
    return {
      loading: '',
      status: null,
      message: '',
      showDialog: false,
      process: 0
    }
  },

  watch: {
    status() {
      let status = this.status
      if (status === -1) {
        this.$message({
          type: 'error',
          center: true,
          message: `${this.message}`
        })
      } else if (status === 1) {
        this.$message.closeAll()
        this.$message({
          type: 'info',
          center: true,
          message: `${this.message}`,
          iconClass: 'el-icon-loading'
        })
      } else if (status === 2) {
        this.showDialog = true
        this.$message.closeAll()
        this.$message({
          type: 'success',
          center: true,
          message: `${this.message}`,
          iconClass: 'el-icon-loading'
        })
      } else if (status === 3) {
        this.$message.closeAll()
        this.$message({
          type: 'success',
          center: true,
          message: `${this.message}`
        })
      }

      if (status !== 2) {
        this.showDialog = false
      }
    }
  },

  methods: {
    showUpdater() {
      this.showUpdate = true
      ipcRenderer.send('checkForUpdate')
    }
  },

  mounted() {
    ipcRenderer.on('message', (event, obj) => {
      console.log('obj', obj)
      this.status = obj.status
      this.message = obj.message
    })

    // 注意:“downloadProgress”事件可能存在无法触发的问题,只需要限制一下下载网速就好了
    ipcRenderer.on('downloadProgress', (event, progressObj) => {
      console.log('progressObj', progressObj)
      console.log('progressObj.percent', progressObj.percent)
      this.process = progressObj.percent || 0

      if (this.process === 100) {
        this.showDialog = false
      }
    })

    // ipcRenderer.on('isUpdateNow', () => {
    //   ipcRenderer.send('isUpdateNow')
    // })
  },

  destroyed() {
    ipcRenderer.removeAllListeners(['message', 'downloadProgress', 'isUpdateNow'])
  }
}
</script>

持续更新中。。。


分享不易,喜欢的话一定别忘了点💖!!!

只关注不点💖的都是耍流氓,只收藏也不点💖的也一样是耍流氓。

结束👍👍👍。


参考

Electron构建跨平台应用Mac/Windows/Linux

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改