electron 自动更新之路总结( 下)客户端 autoUpdate

要说 electron 的自动更新有多难,上篇的版本管理服务器只是开胃菜。真正难啃的是这篇。全文分成 electron 14,electron-updater, electron-builder  三部分。

electron 14

为什么要用 14 版本?因为低于 14 版本用不了 electron-builder 的 NSIS 打包。并且需要把 nodeJs 升级到 12 版本以上。从低版本过来的朋友会发现好多报错,因为 14 做了一篮子改变,改的改删的删, 具体看 Electron 14.0.0 | Electron .

最明显的改变是 remote 的引用方式。旧版是 require('electron').remote ,而新版把 remote 移到了独立的模块 @electron/remote, 使用前必须在main process 中初始化。

// 替换为:
const { BrowserWindow } = require('@electron/remote')

// 在主进程中:
require('@electron/remote/main').initialize()
// 必须有这句,才能在 renderer process 中使用 remote
require("@electron/remote/main").enable(win.webContents)

安装 @electron/remote

npm install @electron/remote -S

使用方法详情 重大更改 | Electron

第二个大变是 webview。原来通过 preload 往网页中注入 js,跟网页共享一个上下文。新版中注入的 js 在单独的上下文,不可跟网页互相调用。

electron-updater

替代 electron 自带的 autoUpdater。后者支持 Squirrel 更新方式,而前者支持 Squirrel、NSIS 等方式。NSIS 有更灵活的可定制性,后面会讲到。根据官方的声明,将来逐步摒弃 Squirrel 转而支持 NSIS. 两者详细差异对比 Auto Update - electron-builder。

两者的 API 大致相同。electron-updater 无需调用 setFeedURL, 而是把 url 写在 package.json.

配置 package.json 

修改 url 为版本服务器地址. build 为 top-level 属性。

"build": {
  "win": {
      "publish": {
        "provider": "generic",
        "url": "http://your-domain/update/win",
        "useMultipleRangeRequest": false
      }
  }
}

加入自动更新代码

const { autoUpdater } = require("electron-updater")
const log = require('electron-log')

// log 初始化,省略

// 检查更新
autoUpdater.logger = log
// 当可更新时在系统通知栏提示
autoUpdater.checkForUpdatesAndNotify()


// 有用户触发安装更新
autoUpdater.quitAndInstall(true, true)

调用 autoUpdater.checkForUpdatesAndNotify() 将检查 http://your-domain/update/win/latest.yml, win 可写成 win32 或 win64,分别代表 32 和 64 位操作系统。有可用更新则自动下载。不想自动下载可设置 autoUpdater.autoDownload = false,然后用 appUpdater.downloadUpdate(cancellationToken) 手动下载。
退出软件时安装新版本。安装包在这里找到 C:\Users\linglq\AppData\Local\fchp-updater\pending。fchp 换成你的 app 的名字。

详细使用方法参考 Auto Update - electron-builder

electron-builder

将 APP 打包成安装包。支持自动更新。选择 NSIS 还可以自定义安装过程。因为实际的项目中需要检测是否安装了某个第三方软件,没有则启动安装,有则忽略。它都能满足。

安装 electron-builder

npm install electron-builder -D

修改 package.json 

  // top-level
  "build": {
    "appId": "appID",
    "win": {
      "target": "nsis",
      "icon": "src/assets/app.ico",
      "publish": {
        "provider": "generic",
        "url": "http://your-domain/update/win",
        "useMultipleRangeRequest": false
      }
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "perMachine": true,
      "deleteAppDataOnUninstall": true,
      "include": "build/installer.nsh"
    },
    "extraResources": [
      {
        "from": "resources/aria2",
        "to": "aria2"
      }
    ]
  },
"script": {
  "pack": "electron-builder --dir",
  "dist": "electron-builder"
}

对上面的配置逐一讲解。

  • oneClick 当为 true 时不显示安装界面,一键安装。跟常见的安装过程不一样
  • allowToChangeInstallationDirectory 允许用户选择安装路径
  • perMachine 当为 true 时,默认安装目录是 c:\program files ; false 时默认安装目录是 c:\用户\当前用户名\AppData。
  • deleteAppDataOnUninstall 卸载时是否删除数据目录
  • include 自定义的安装脚本。例如检测是否需要安装第三方插件等等
  • extraResources 例如将第三方 exe 文件打包进来,将会安装到 resources 目录下

开始打包

npm run pack 只生成文件和目录,不打包成 exe
npm run dist 打包成最终的安装文件,以及.blockmap文件

接下来看看是如何做到检测第三方软件的
build/installer.nsh

!macro customInstall
  ReadRegStr $0 HKLM "SOFTWARE\GPL Ghostscript\9.27" "GS_LIB"
  StrCmp $0 "" 0 skip_ghost_script
  File /oname=$PLUGINSDIR\gs927w32.exe "${BUILD_RESOURCES_DIR}\gs927w32.exe"
  ExecWait '"$PLUGINSDIR\gs927w32.exe" /sw'
  
  skip_ghost_script:
    ;;
  ReadRegStr $0 HKLM "SOFTWARE\GraphicsMagick\Current" "Version"
  StrCmp $0 "" 0 skip_graphic_magick
  File /oname=$PLUGINSDIR\GraphicsMagick-1.3.33-Q8-win32-dll.exe "${BUILD_RESOURCES_DIR}\GraphicsMagick-1.3.33-Q8-win32-dll.exe"
  ExecWait '"$PLUGINSDIR\GraphicsMagick-1.3.33-Q8-win32-dll.exe" /sw'

  skip_graphic_magick:
    ;;
!macroend

大抵的意思是 ReadRegStr 读取注册表字段,判断软件是否存在。没有就用 ExecWait 启动安装,并且等待安装完成。有就略过。

第三方 exe、msi 放在 build 目录下。 对于 msi 引用方式稍微改变一下
ExecWait '"msiexec" /i "$PLUGINSDIR\extramsi.msi" /passive'

 更详细的 NSIS 语法看 https://github.com/NSIS-Dev/Documentation/tree/master/Reference

electron 自动更新之路总结( 下)客户端 autoUpdate_第1张图片

electron-builder 跟 electron-packager 的区别

两者都是将源码打包成  asar 格式。不同的是,前者生产的文件更大。同一份代码,electron-builder 打包出来的程序有 200M,而 electron-packager 只有 100M。相差近一倍。

还有更大的不同在于写文件方面。electron-packager 生成的是绿色包,可在程序所在目录下面任意读写文件。而 electron-builder 不一样,生成的安装包安装到系统以后,不能再程序目录写入文件或新建目录,否则报“权限不足”的错误。那缓存和数据文件应该怎么保存呢?正确的方法是写到用户的数据目录。

const logDir = path.join(app.getPath('userData'), 'logs')
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir, { recursive: true });
}

以笔者为例,文件保存到了 C:\Users\linglq\AppData\Roaming\fchp\logs

你可能感兴趣的:(互联网,electron,前端,自动更新,autoUpdate)