electron electron-updater热更新 + 踩坑详解

背景: 已经开发完的vue2项目,在此基础上进行打包并用进行热更新。
Electron官网

关于nodejs

我一开始用的18版本,但是会有报错,针对报错试了网上能找到的所有方法,都没解决,最终降版本了,降到了v14.21.3版本,至此nodejs问题解决。

关于打包后跳转失效

1、必须使用hash模式,否则打包后路由跳转失效
2、如果项目中用了 js-cookie 插件也是不行的,建议存到本地
在这里插入图片描述

步骤

1、首先需要确保安装了vue CLI

npm install -g @vue/cli

2、安装electron打包模块

vue add electron-builder

本人选择了12的版本,有的网友说13的版本不太稳定,因为忙没去测试。
在这里插入图片描述
安装完成后在package.json中会多这两行代码,分别是打包命令和运行命令。
在这里插入图片描述
同时会在与main.js同级里面看到background.js,这个文件就是electron的主文件,其中设置窗口的大小位置、热更新等都在这里开发。
在这里插入图片描述

3、安装完成后启动看下效果

npm run electron:serve

在这里插入图片描述
有个警告,不碍事 -_-
启动成功后会弹出electron的窗口。到此启动成功,未开发的功能就可以继续开发了。

在开发中会自动打开开发者工具,但是打包后就没有了,如果看网络请求和dom之类的可以按照下图的配置打开工具,但是console无法看到,如果要看console可以根据网上配置,也可以用electron的dialog模块

const {dialog} = require('electron')//弹窗的方式
dialog.showMessageBox(mainWin, {
      type: 'info',
      buttons: ['OK'],
      title: '检测更新...',
      message: '检测更新'
  });

如果要看需要配置,更多窗口配置和其他配置可以看官网,也可以看w3c的 https://www.w3cschool.cn/electronmanual/
在这里插入图片描述

  const win = new BrowserWindow({
    width: 800,//窗口的宽度
    height: 600,//窗口的高度
    webPreferences: {
      nodeIntegration:true,
      contextIsolation:false,
      webSecurity:false,//是否开启代理
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      // contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
    }
  })
  // 在主进程中打开开发者工具
  win.webContents.openDevTools()
  Vue.config.devtools = false

打包

1、运行打包命令 npm run electron:build
成功后会生成一个dist_electron文件夹,里面会有安装文件,如果是为了看打包后的效果,win-unpacked文件夹里面也有一个exe文件,可以不用安装程序查看打包后的效果
在这里插入图片描述

electron-updater热更新

1、首先安装electron-updater

npm i electron-updater

2?安装完成后确认更新流程,更新一般是通过版本校验,本地版本低于线上版本的话进行下载线上版本并安装的过程,因此在打包的时候需要同时生成一个yml文件,用来校验版本和定义下载内容,因此需要修改打包文件。有的人通过npm下载的electron-builder会生成一个builder.js文件,但是通过vue add没有这个文件,我们在vue.config.js里面添加就行,放在module.exports里面,代码如下:

特别注意:url很重要,地址要么是http的,如果你用https千万是正规的ssl,不然没用,因为这个找了整整一天的问题

 pluginOptions: {
    electronBuilder: {
        nodeIntegration: true,
        builderOptions: {
            nsis: {},
            asar: false,
            "publish": [
                {
                  "provider": "generic",
                  "url": "https://xxx.xxx.xxx/file/"//你线上服务器的地址,其中file文件夹里面有你下一步生成的yml和exe文件
                }
              ],
        }
    }
  },

配置完之后进行打包,完成后会有一个yml文件,这个文件和exewenjian 需要你上传到服务器,放在file文件夹里面
在这里插入图片描述
3、接下来进行编写更新代码,创建一个update.js,里面代码如下

const { autoUpdater } = require('electron-updater');
const {dialog} = require('electron')
var mainWin = null;
export const checkUpdate = (win, ipcMain) => {
  
  autoUpdater.autoInstallOnAppQuit = true; // 应用退出后自动安装
  mainWin = win;

  // autoUpdater.checkForUpdatesAndNotify();
  //校验地址
  autoUpdater.setFeedURL({ provider: "generic",url: 'https://xxx.xxx.xxx/file/' });
  autoUpdater.autoDownload = true; // 自动下载
  autoUpdater.checkForUpdates();
  
  // 检测是否有更新包并通知
  autoUpdater.on('error', (error) => {
    // 下载完成后强制用户安装,不推荐
    // autoUpdater.quitAndInstall();
  });
   //监听开始检测更新事件
   autoUpdater.on('checking-for-update', function (message) {
    console.info('检测更新')
    dialog.showMessageBox(mainWin, {
      type: 'info',
      buttons: ['OK'],
      title: '检测更新...',
      message: '检测更新'
  });
});
//监听发现可用更新事件
autoUpdater.on('update-available', function (message) {
    console.info('有可用更新')
    dialog.showMessageBox(mainWin, {
        type: 'info',
        buttons: ['OK'],
        title: '下载更新中,请等待...',
        message: '下载完成后会自动安装'
    });
});
//监听没有可用更新事件
autoUpdater.on('update-not-available', function (message) {
  dialog.showMessageBox(mainWin, {
    type: 'info',
    buttons: ['OK'],
    title: '没有更新...',
    message: '没有更新'
});
 
});
  autoUpdater.on('download-progress', (prog) => {
  //通过preload.js进行通信,来显示进度条
    mainWin.webContents.send('update', {
      speed: Math.ceil(prog.bytesPerSecond / 1000), // 网速
      percent: Math.ceil(prog.percent), // 百分比
    });
  });
  autoUpdater.on('update-downloaded', (info) => {
    dialog.showMessageBox(mainWin, {
      type: 'info',
      buttons: ['OK'],
      title: '下载完成',
      message: '下载完成'
  });
    mainWin.webContents.send('downloaded');
    // 下载完成后强制用户安装,不推荐
    autoUpdater.quitAndInstall();
  });
  // 监听渲染进程的 install 事件,触发退出应用并安装
  ipcMain.handle('install', () => autoUpdater.quitAndInstall());
};

// module.exports = checkUpdate;

这是所有的更新流程,其中会用到的文件代码
preload.js文件需要放在public和dist_electron里面
在这里插入图片描述

const { ipcRenderer } = require('electron');
 
window.elecAPI = {
  toInstall: () => ipcRenderer.invoke('install'),
  onUpdate: (callback) => ipcRenderer.on('update', callback),
  onDownloaded: (callback) => ipcRenderer.on('downloaded', callback),
};

background.js文件

'use strict'

import { app, protocol, BrowserWindow ,ipcMain } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
const path = require('path');
const preload = path.join(__dirname, './preload.js');
import Vue from 'vue'
import {checkUpdate} from './update.js'

var win

const isDevelopment = process.env.NODE_ENV !== 'production'

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: 'app', privileges: { secure: true, standard: true } }
])

async function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 1600,
    height: 1000,
    webPreferences: {
      
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      // contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
      nodeIntegration:true,
      contextIsolation:false,
      webSecurity:false,
      devTools: true,
      preload
    }
  })
  // 在主进程中打开开发者工具
  win.webContents.openDevTools()
  Vue.config.devtools = true
  // 检查更新
  checkUpdate(win, ipcMain);
  // 在渲染进程中打开开发者工具
  // if (process.env.NODE_ENV === 'development') {
  //   Vue.config.devtools = true
  // }
  // 关闭工具栏
  win.setMenu(null)
  // 应用全屏
  win.setFullScreen(false);

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await 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')
    // win.loadFile('./index.html')
  }
}

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS 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 (BrowserWindow.getAllWindows().length === 0) createWindow()
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
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()
    })
  }
}

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值