vue+electron 打包,自动更新,修改默认安装目录

使用

克隆项目

git clone https://gitee.com/code_yu/hx-electron.git

cd hx-electron

安装依赖

yarn install

开发环境启动

yarn electron:serve

正式打包

yarn electron:build

技术栈 文档

如需查看打包后应用的日志,那么需从命令行启动应用

$ cd demo_path
$ ./demo.exe

应用自动更新

1. 配置 vue.config.js 中的应用更新服务器地址

详细打包配置请看 vue.config.js 完整示例

module.exports = {
  pluginOptions: {
    electronBuilder: {
        ...
        
        publish: [
          {
            provider: 'generic',
            url: 'http://127.0.0.1/app/'
          }
        ]

        ...

      }
    }
  }
}

2. 在主进程写更新应用逻辑

background.js 文件或 main.js 中写入更新逻辑

以下为 background.js 完整示例:

'use strict'

import { app, protocol, BrowserWindow, Menu, dialog } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const { autoUpdater } = require('electron-updater')
const path = require('path')
const log = require('electron-log')
const isDevelopment = process.env.NODE_ENV !== 'production'

let win

protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

log.info('启用日志')

function createWindow () {
  Menu.setApplicationMenu(null)
  // Create the browser window.
  win = new BrowserWindow({
    width: 1400,
    height: 800,
    webPreferences: {
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      preload: path.join(__dirname, 'preload.js')
    }
  })

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
    autoUpdater.checkForUpdates()
  }

  win.on('closed', () => {
    win = null
  })
}

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

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

app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  createWindow()
})

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}

// ======================================================================
// 更新模块
// ======================================================================
if (!process.env.WEBPACK_DEV_SERVER_URL) {
  autoUpdater.autoDownload = false

  autoUpdater.signals.updateDownloaded(() => {})
  autoUpdater.on('error', (error) => {
    log.warn('检查更新失败: ' + error == null ? 'unknown' : (error.stack || error).toString())
    // dialog.showErrorBox('Error: ', error == null ? 'unknown' : (error.stack || error).toString())
  })

  autoUpdater.on('update-available', (info) => {
    // var appInfo = {
    //   info: info.version,
    //   files: info.files,
    //   path: info.path,
    //   sha512: info.sha512,
    //   releaseDate: info.releaseDate
    // }
    dialog.showMessageBox({
      type: 'info',
      title: '更新提示',
      message: '软件需要更新,您是否立即更新?',
      buttons: ['推迟', '立即更新']
    }).then((res) => {
      log.warn('index:' + res.response)
      if (res.response === 1) {
        log.warn('选择升级')
        autoUpdater.downloadUpdate()
      } else {
        log.warn('选择不升级:')
      }
    })
  })

  // 检查更新时触发
  autoUpdater.on('update-available', (res) => {
    log.warn('检查更新时触发')
    // log.warn(res)
    // dialog.showMessageBox({
    //   title: '检查更新',
    //   message: '正在检查更新'
    // })
  })

  // 没有可用更新
  autoUpdater.on('update-not-available', () => {
    log.warn('没有可用更新')
    // dialog.showMessageBox({
    //   title: '已是最新版',
    //   message: '当前版本是最新版本。'
    // })
  })

  // 安装更新
  autoUpdater.on('update-downloaded', (res) => {
    // log.warn(res)
    log.warn('下载完毕!提示安装更新')
    dialog.showMessageBox({
      title: '升级提示!',
      message: '已自动升级为最新版,请重启应用!'
    }, () => {
      log.warn('确认安装')
      setImmediate(() => autoUpdater.quitAndInstall(true, true))
    })
  })

  // 下载进度
  // autoUpdater.on('download-progress', (event) => {
  //   log.warn(event.percent)
  // })
}


3. 打包一个应用(v1.0.0)

打包后 dist_electron 目录中有 *.blockmap 格式的文件;

将文件复制到 ‘更新服务器’ (http://127.0.0.1/app/) 目录下;

4. 打包一个升级版的应用(v1.1.0)

打包后 dist_electron 有如下三个文件:

  • 新版本安装包.exe
  • 新版本_v1.1.0.blockmap
  • latest.yml

将上面三个文件复制到 ‘更新服务器’ (http://127.0.0.1/app/) 目录下;

以后每次有更新就复制这三个文件至 ‘更新服务器’,保留旧版本的 *.blockmap 文件,旧版本的应用的执行文件(.exe)可以删除。

其他

打包

打包配置 vue.config.js 完整示例

module.exports = {
  pluginOptions: {
    electronBuilder: {
      // 预加载文件
      preload: 'src/preload.js',
      // 渲染进程也可以获取原生node包
      nodeIntegration: true,
      // 打包配置
      builderOptions: {
        // 发布者名称
        productName: 'hx-admin',
        // 包名
        appId: 'cn.xxx.hxadmin',
        copyright: 'hui xian copyright',
        // 更新的服务器
        publish: [
          {
            provider: 'generic',
            url: 'http://127.0.0.1/app/'
          }
        ],
        asar: false,
        // 不需要打包至asar中的文件如数据库文件,icons文件
        extraResources: [
          {
            from: './data/db.db',
            to: '../data/db.db',
            filter: ['**/*']
          }, './icons'],
        win: {
          // 图标文件大小为 256*256
          icon: './icons/icon.ico',
          target: [
            {
              target: 'nsis',
              arch: [
                // 'x64',
                'ia32'
              ]
            }
          ],
          // 打包权限 asInvoker | highestAvailable
          requestedExecutionLevel: 'highestAvailable'
        },
        // 安装包名称,可自行配置
        artifactName: '${productName}_Setup_${version}_${platform}.${ext}',
        nsis: {
          // 一键安装,如果设为true,nsis设置就无意义请直接删除 nsis 配置
          oneClick: false,
          // true全用户安装【目录为:C:\Program Files (x86)】,false安装到当前用户
          perMachine: true,
          // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
          allowElevation: true,
          // 允许修改安装目录
          allowToChangeInstallationDirectory: true,
          // 创建桌面图标
          createDesktopShortcut: true,
          // 创建开始菜单图标
          createStartMenuShortcut: true,
          // 快捷方式的名称,默认为应用程序名称
          // shortcutName: 'HX',
          // 安装图标
          installerIcon: './icons/icon.ico',
          // 卸载图标
          uninstallerIcon: './icons/icon.ico',
          // 安装时头部图标
          installerHeaderIcon: './icons/icon.ico',
          // 配置 nsn 如修改默认安装目录
          include: './installer.nsh'
        }
      }
    }
  }
}

安装时修改默认目录

1. 在 nsis 添加 include 属性:

详细打包配置请看 vue.config.js 完整示例

module.exports = {
  pluginOptions: {
    electronBuilder: {
        ...
        
        nsis: {
          // 配置 nsn 如修改默认安装目录
          include: './installer.nsh'

          ...
        }

        ...
      }
    }
  }
}

2. 根目录新建 installer.nsh 文件,内容如下:

installer.nsh 一般和vue.config.js为同级目录

D:\Program Files (x86) 为定义安装目录,可修改

${PRODUCT_NAME} 为应用名称变量,一般没不需要改

!macro preInit
  SetRegView 64
  WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files\${PRODUCT_NAME}"
  WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files\${PRODUCT_NAME}"
  SetRegView 32
  WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files (x86)\${PRODUCT_NAME}"
  WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "D:\Program Files (x86)\${PRODUCT_NAME}"
!macroend
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Electron Vue 项目中,当我们使用 iframe 标签来嵌入其他网页时,有时会出现跨域问题。这是因为 Electron 应用默认是禁止跨域请求的,为了解决这个问题,我们可以进行以下操作: 1. 在项目的主进程中的 main.js 文件中,添加以下代码来启用跨域请求: ```javascript const electron = require('electron') electron.webContents.allowRendererProcessReuse = true app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors') ``` 这样,我们就可以解决 electron 的跨域请求问题。 2. 如果还是无法解决跨域问题,我们可以在 vue.config.js 文件中进行配置。在 devServer 配置下增加以下代码: ```javascript devServer: { proxy: { '/api': { target: 'http://localhost:3000', ws: true, changeOrigin: true } } } ``` 这样,在开发环境下,我们将所有以 '/api' 开头的请求都代理到我们指定的 target 地址上,解决跨域问题。 3. 如果以上两种方法都无效,我们还可以在 Electron 的主进程中使用 session 来禁用 webSecurity,代码如下: ```javascript const { app, BrowserWindow } = require('electron') app.on('ready', () => { const mainWindow = new BrowserWindow({ webPreferences: { webSecurity: false } }) }) ``` 这样,我们就可以通过禁用 webSecurity 来解决 Electron 的跨域问题。 需要注意的是,这些解决方法只适用于开发环境和本地调试阶段。在最终打包发布 Electron Vue 项目时,需要遵循 Electron 的安全策略,并且谨慎处理跨域问题,以确保项目的安全性和稳定性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值