用得到的electron开发总结

3,531 阅读4分钟

Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。

检查Electron是否正在开发中运行

const electron = require("electron");
const isDev = !electron.app.isPackaged

实现自动更新

使用 electron-builder 结合 electron-updater 实现自动更新。

主进程添加自动更新检测和事件监听:

import { autoUpdater } from "electron-updater"
import { ipcMain } from "electron"

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

  autoUpdater.setFeedURL('https://xxx.xxxx.com/');
  autoUpdater.on('error', function (error) {
    console.log(error)
    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')
  });

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

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

在视图(View)层中触发自动更新,并添加自动更新事件的监听。

触发自动更新:

  ipcRenderer.send("checkForUpdate");

监听自动更新事件:

    ipcRenderer.on("message", (event, text) => {
      console.log(text)
    });
    ipcRenderer.on("downloadProgress", (event, progressObj)=> {
      console.log(progressObj.percent)
      this.setState({
        downloadPercent: parseInt(progressObj.percent) || 0
      })
    });
    ipcRenderer.on("isUpdateNow", () => {
        ipcRenderer.send("isUpdateNow");
    });

为避免多次切换页面造成监听的滥用,切换页面前必须移除监听事件:

ipcRenderer.removeAll(["message", "downloadProgress", "isUpdateNow"]);

参考地址 segmentfault.com/a/119000001…

使用 electron-builder 打包配置

electron-builder.yaml文件配置如下

directories:
  buildResources: buildResources
  output: dist
appId: cube.create-desktop
productName: "Create 3"
publish: # empty provider list = don't publish
mac:
  category: public.app-category.education
  entitlements: buildResources/entitlements.mac.plist
  extendInfo:
    NSCameraUsageDescription: >-
        This app requires camera access when using the video sensing blocks.
    NSMicrophoneUsageDescription: >-
        This app requires microphone access when recording sounds or detecting loudness.
  gatekeeperAssess: true
  hardenedRuntime: true
  icon: buildResources/CreateDesktop.icns
  provisioningProfile: embedded.provisionprofile
  artifactName: "Create ${version}.${ext}"
  target:
    - dmg
    - mas
dmg:
  title: "Create ${version}"
mas:
  category: public.app-category.education
  entitlements: buildResources/entitlements.mas.plist
  entitlementsInherit: buildResources/entitlements.mas.inherit.plist
  hardenedRuntime: false
  icon: buildResources/CreateDesktop.icns
masDev:
  type: development
  provisioningProfile: mas-dev.provisionprofile
win:
  icon: buildResources/CreateDesktop.ico
  target:
    - appx
    - nsis
appx:
  identityName: CreateFoundation.CreateDesktop
  publisherDisplayName: "Create Foundation"
  publisher: "CN=2EC43DF1-469A-4119-9AB9-568A0A1FF65F"
  artifactName: "Create ${version} ${arch}.${ext}"
nsis:
  oneClick: false # allow user to choose per-user or per-machine
  artifactName: "Create ${version} Setup.${ext}"

限制开启一个electron实例

app.requestSingleInstanceLock()方法的返回值表示你的应用程序实例是否成功取得了锁。 如果它取得锁失败,你可以假设另一个应用实例已经取得了锁并且仍旧在运行,并立即退出。

即: 如果当前进程是应用程序的主要实例,则此方法返回true,同时你的应用会继续运行。 如果当它返回 false如果你的程序没有取得锁,它应该立刻退出,并且将参数发送给那个已经取到锁的进程。

在 macOS 上, 当用户尝试在 Finder 中打开您的应用程序的第二个实例时, 系统会通过发出 open-file 和 open-url 事件来自动强制执行单个实例,。 但是当用户在命令行中启动应用程序时, 系统的单实例机制将被绕过, 您必须手动调用此方法来确保单实例。

在第二个实例启动时激活主实例窗口的示例:

const { app } = require('electron')
let myWindow = null

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // 当运行第二个实例时,将会聚焦到myWindow这个窗口
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })

  // 创建 myWindow, 加载应用的其余部分, etc...
  app.whenReady().then(() => {
    myWindow = createWindow()
  })
}

windows平台 serialport 串口编译

如果需要serialport作为Electron项目的依赖项,则必须针对项目使用的Electron版本对其进行编译。

对于大多数最常见的用例(标准处理器平台上的Linux,Mac,Windows),我们使用prebuild来编译和发布库的二进制文件。 使用nodejs进行编译node-gyp需要使用Python 2.x,因此请确保已安装它,并且在所有操作系统的路径中。Python 3.x无法正常工作。

安装windows构建工具和配置想省时省力请选择以下方案:

npm install --global --production windows-build-tools

上边命令决定串口编译是否成功。安装过程非常缓慢,安装完成就等于串口编译成功了99%。

手动安装工具和配置请看github.com/nodejs/node…

接下来用 electron-rebuild 包重建模块以适配 Electron。这个包可以自动识别当前 Electron 版本,为你的应用自动完成下载 headers、重新编译原生模块等步骤。

"scripts": {
    "rebuild": "electron-rebuild"
}

执行以下命令完成串口编译

npm run rebuild

注意:

  • 编译过的串口不同系统不可通用,需在各平台重新编译
  • windows系统最好是正版,或净化版。否正很有可能安装失败。