在windows平臺下electron-builder實現前端程序的打包與自動更新

因爲8月份上旬公司開發一款桌面應用程序,在前端開發程序打包更新時遇到一些困擾多日的問題,採用electron-builder最終仍是獲得解決~html

如下是踩坑的過程及對electron打包與更新思路的梳理,electron打包與更新的正確姿式應該以下圖所示前端

下面將逐一展開描述說明vue

    1、windows系統下環境配置

NPM是隨NodeJS一塊兒安裝的包管理工具,能解決NodeJS代碼部署上的不少問題node

  • 容許用戶從NPM服務器下載別人編寫的第三方包到本地使用。
  • 容許用戶從NPM服務器下載並安裝別人編寫的命令行程序到本地使用。
  • 容許用戶將本身編寫的包或命令行程序上傳到NPM服務器供別人使用。

在windows平臺系統下,使用cmd命令設置npm安裝模塊、electron打包所需環境linux

npm config set prefix "C:\Program Files (x86)\nodejs\npm_global" 設置全局模塊安裝路徑
npm config set cache "C:\Program Files (x86)\nodejs\npm_cache" 設置緩存文件夾
npm config set registry "https://registry.npm.taobao.org" 設置淘寶鏡像
electron npm config set electron_mirror "https://npm.taobao.org/mirrors/electron/"  electron能夠經過設置淘寶鏡像快速下載
npm config set arch ia32
npm config set target_arch ia32
npm config set disturl https://npm.taobao.org/mirrors/atom-shell
npm config set runtime electron
npm config set build_from_source true

    2、打包成可執行的運行包

electron-quick-start中,配置文件package.json中添加一句,經過npm包管理器npm install依賴模塊與 npm install electron-packager --savegit

"scripts": {
    "package": "electron-packager ./ --overwrite -all"
}

執行npm run package 命令,便可獲得可執行運行包,可運行包內部大體說明以下圖github

 因爲"../electron-quick-start/electron-quick-start-win32-ia32/resources/app"路徑下開發項目代碼資源是裸露的,出於安全性和代碼保護性考慮web

因此須要asar對開發項目資源進行二進制加密,asar加密文件可讀不可寫.shell

    3、將打包成可執行的運行包進行asar二進制加密

安裝  npm install --save-dev asar 
安裝完成之後,就可使用asar命令將裸露程序文件打包了 asar pack ./app app.asar 
後將app文件移除掉便可npm

    4、使用NSIS將可執行的運行包打成安裝包

在windows系統下采用NSIS將打包成可安裝程序

下載前至NSIS 3.0 .1正式版漢化加強版

使用VNISEdit 編譯環境具體教程請參考win7下nsis打包exe安裝程序教程

生成腳本

  1 ; 該腳本使用 HM VNISEdit 腳本編輯器嚮導產生
  2 
  3 ; 安裝程序初始定義常量
  4 !define PRODUCT_NAME "My application"
  5 !define PRODUCT_VERSION "1.0"
  6 !define PRODUCT_PUBLISHER "My company, Inc."
  7 !define PRODUCT_WEB_SITE "http://www.mycompany.com"
  8 !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\electron-quick-start.exe"
  9 !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
 10 !define PRODUCT_UNINST_ROOT_KEY "HKLM"
 11 
 12 SetCompressor lzma
 13 
 14 ; ------ MUI 現代界面定義 (1.67 版本以上兼容) ------
 15 !include "MUI.nsh"
 16 
 17 ; MUI 預約義常量
 18 !define MUI_ABORTWARNING
 19 !define MUI_ICON "app.ico"
 20 !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
 21 
 22 ; 歡迎頁面
 23 !insertmacro MUI_PAGE_WELCOME
 24 ; 許可協議頁面
 25 !insertmacro MUI_PAGE_LICENSE "..\YourSoftwareLicence.txt"
 26 ; 安裝目錄選擇頁面
 27 !insertmacro MUI_PAGE_DIRECTORY
 28 ; 安裝過程頁面
 29 !insertmacro MUI_PAGE_INSTFILES
 30 ; 安裝完成頁面
 31 !define MUI_FINISHPAGE_RUN "$INSTDIR\electron-quick-start.exe"
 32 !insertmacro MUI_PAGE_FINISH
 33 
 34 ; 安裝卸載過程頁面
 35 !insertmacro MUI_UNPAGE_INSTFILES
 36 
 37 ; 安裝界面包含的語言設置
 38 !insertmacro MUI_LANGUAGE "SimpChinese"
 39 
 40 ; 安裝預釋放文件
 41 !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
 42 ; ------ MUI 現代界面定義結束 ------
 43 
 44 Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
 45 OutFile "Setup.exe"
 46 InstallDir "$PROGRAMFILES\My application"
 47 InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
 48 ShowInstDetails show
 49 ShowUnInstDetails show
 50 
 51 Section "MainSection" SEC01
 52   SetOutPath "$INSTDIR"
 53   SetOverwrite ifnewer
 54   File /r "*.*"
 55   CreateDirectory "$SMPROGRAMS\My application"
 56   CreateShortCut "$SMPROGRAMS\My application\My application.lnk" "$INSTDIR\electron-quick-start.exe"
 57   CreateShortCut "$DESKTOP\My application.lnk" "$INSTDIR\electron-quick-start.exe"
 58   File "electron-quick-start.exe"
 59 SectionEnd
 60 
 61 Section -AdditionalIcons
 62   WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
 63   CreateShortCut "$SMPROGRAMS\My application\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
 64   CreateShortCut "$SMPROGRAMS\My application\Uninstall.lnk" "$INSTDIR\uninst.exe"
 65 SectionEnd
 66 
 67 Section -Post
 68   WriteUninstaller "$INSTDIR\uninst.exe"
 69   WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\electron-quick-start.exe"
 70   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
 71   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
 72   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\electron-quick-start.exe"
 73   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
 74   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
 75   WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
 76 SectionEnd
 77 
 78 /******************************
 79  *  如下是安裝程序的卸載部分  *
 80  ******************************/
 81 
 82 Section Uninstall
 83   Delete "$INSTDIR\${PRODUCT_NAME}.url"
 84   Delete "$INSTDIR\uninst.exe"
 85   Delete "$INSTDIR\electron-quick-start.exe"
 86 
 87   Delete "$SMPROGRAMS\My application\Uninstall.lnk"
 88   Delete "$SMPROGRAMS\My application\Website.lnk"
 89   Delete "$DESKTOP\My application.lnk"
 90   Delete "$SMPROGRAMS\My application\My application.lnk"
 91 
 92   RMDir "$SMPROGRAMS\My application"
 93 
 94   RMDir /r "$INSTDIR\resources"
 95   RMDir /r "$INSTDIR\locales"
 96 
 97   RMDir "$INSTDIR"
 98 
 99   DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
100   DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
101   SetAutoClose true
102 SectionEnd
103 
104 #-- 根據 NSIS 腳本編輯規則,全部 Function 區段必須放置在 Section 區段以後編寫,以免安裝程序出現未可預知的問題。--#
105 
106 Function un.onInit
107   MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您確實要徹底移除 $(^Name) ,及其全部的組件?" IDYES +2
108   Abort
109 FunctionEnd
110 
111 Function un.onUninstSuccess
112   HideWindow
113   MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地從您的計算機移除。"
114 FunctionEnd
View Code

    5、windows系統安裝程序更新

安裝npm install  electron-updater 在應用中觸發更新檢查, electron-updater 自動會經過對應url下的yml文件檢查更新

在入口文件main.js中需注意

1 //if you don't use ES6: const autoUpdater = require("electron-updater").autoUpdater
2 const autoUpdater = require('electron-updater').autoUpdater
//ipcMain 主線程
const ipcMain = require('electron').ipcMain

autoUpdater

  1 // 檢測更新,在你想要檢查更新的時候執行,renderer事件觸發後的操做自行編寫
  2 function updateHandle(){
  3     //minimize
  4     ipcMain.on('hide-window', () => {
  5         mainWindow.minimize();
  6     });
  7     //maximize
  8     ipcMain.on('show-window', () => {
  9         mainWindow.maximize();
 10     });
 11     //unmaximize
 12     ipcMain.on('orignal-window', () => {
 13         mainWindow.unmaximize();
 14     });
 15     //打開默認瀏覽器
 16     ipcMain.on('open-office-website', function(event, arg){
 17         shell.openExternal(arg)
 18     })
 19     
 20     ipcMain.on('check-for-update', function(event, arg) {
 21         let message={
 22             appName:'智卡桌面應用討論',
 23             error:'檢查更新出錯, 請聯繫開發人員',
 24             checking:'正在檢查更新……',
 25             updateAva:'檢測到新版本,正在下載……',
 26             updateNotAva:'如今使用的就是最新版本,不用更新',
 27             downloaded: '最新版本已下載,將在重啓程序後更新'
 28         };
 29         //設置檢查更新的 url,而且初始化自動更新。這個 url 一旦設置就沒法更改。
 30         const updateFeedUrl='http://www.baidu.com/updates/latest/win/';
 31         if(os.platform()==='darwin'){
 32             updateFeedUrl='http://www.baidu.com/updates/latest/mac/';
 33         }
 34         autoUpdater.setFeedURL(updateFeedUrl);
 35 
 36         autoUpdater.on('error', function(error){
 37             return dialog.showMessageBox(mainWindow, {
 38                     type: 'info',
 39                     buttons: ['OK'],
 40                     title: message.appName,
 41                     message: message.errorTips,
 42                     detail: '\r' + message.error
 43                 });
 44 
 45             sendUpdateMessage(message.error)
 46         });
 47 
 48         //當開始檢查更新的時候觸發
 49         autoUpdater.on('checking-for-update', function() {
 50             sendUpdateMessage(message.checking)
 51             return dialog.showMessageBox(mainWindow, {
 52                     type: 'info',
 53                     buttons: ['OK'],
 54                     title: message.appName,
 55                     message: message.checking
 56                 });
 57         });
 58 
 59         //當發現一個可用更新的時候觸發,更新包下載會自動開始
 60         autoUpdater.on('update-available', function(info) {
 61             sendUpdateMessage(message.updateAva)
 62             var downloadConfirmation = dialog.showMessageBox(mainWindow, {
 63                 type: 'info',
 64                 buttons: ['OK'],
 65                 title: message.appName,
 66                 message: message.updateAva
 67             });
 68             if (downloadConfirmation === 0) {
 69                 return;
 70             }
 71         });
 72 
 73         //當沒有可用更新的時候觸發
 74         autoUpdater.on('update-not-available', function(info) {
 75             return dialog.showMessageBox(mainWindow, {
 76                 type: 'info',
 77                 buttons: ['OK'],
 78                 title: message.appName,
 79                 message: message.updateNotAva
 80             });
 81             sendUpdateMessage(message.updateNotAva)
 82         });
 83         
 84         // 更新下載進度事件
 85         autoUpdater.on('download-progress', function(progressObj) {
 86             mainWindow.webContents.send('downloadProgress', progressObj)
 87         })
 88         /**
 89          *  event Event
 90          *  releaseNotes String - 新版本更新公告
 91          *  releaseName String - 新的版本號
 92          *  releaseDate Date - 新版本發佈的日期
 93          *  updateURL String - 更新地址
 94          * */
 95         autoUpdater.on('update-downloaded',  function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
 96             var index = dialog.showMessageBox(mainWindow, {
 97                 type: 'info',
 98                 buttons: ['如今重啓', '稍後重啓'],
 99                 title: message.appName,
100                 message: message.downloaded,
101                 //detail: releaseName + "\n\n" + releaseNotes
102             });
103             console.log(index);
104             if (index === 1) return;
105             //在下載完成後,重啓當前的應用而且安裝更新
106             autoUpdater.quitAndInstall();
107             //經過main進程發送事件給renderer進程,提示更新信息
108             //mainWindow.webContents.send('isUpdateNow')
109         });
110         
111         //執行自動更新檢查
112         autoUpdater.checkForUpdates();
113     });
114 }

 Squirrel.Windows 是windows系統下electron-updater 檢查更新lib庫 

關於Squirrel.Windows 更詳細說明,請鏈接至 https://github.com/Squirrel/Squirrel.Windows

Squirrel is both a set of tools and a library, to completely manage both installation and updating your Desktop Windows application, 
written in either C# or any other language (i.e., Squirrel can manage native C++ applications).  

    6、主線程與渲染線程之間通訊

點擊更新按鈕後

1 //檢查更新
2  $("#accLogin").find(".T-updateApp").on("click", function() {
3          setTimeout(function() {
4              //update 渲染進程 
5              ipcr.send('check-for-update', 'event-update');
6          }, 20);
7 });

觸發主線程(上述步驟五 updateHandle 方法中) ipcMain.on('check-for-update', function(event, arg) { //執行操做 }) 檢查更新 autoUpdater各類狀態

ipcMain.on('check-for-update', function(event, arg) {
        //設置檢查更新的 url,而且初始化自動更新。這個 url 一旦設置就沒法更改。
        const updateFeedUrl='http://www.baidu.com/updates/latest/win/';
        if(os.platform()==='darwin'){
            updateFeedUrl='http://www.baidu.com/updates/latest/mac/';
        }
        autoUpdater.setFeedURL(updateFeedUrl);

        autoUpdater.on('error', function(error){});

        //當開始檢查更新的時候觸發
        autoUpdater.on('checking-for-update', function() {});

        //當發現一個可用更新的時候觸發,更新包下載會自動開始
        autoUpdater.on('update-available', function(info) {});

        //當沒有可用更新的時候觸發
        autoUpdater.on('update-not-available', function(info) {});
        
        // 更新下載進度事件
        autoUpdater.on('download-progress', function(progressObj) {})
        /**
         *  event Event
         *  releaseNotes String - 新版本更新公告
         *  releaseName String - 新的版本號
         *  releaseDate Date - 新版本發佈的日期
         *  updateURL String - 更新地址
         * */
        autoUpdater.on('update-downloaded',  function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {});
        
        //執行自動更新檢查
        autoUpdater.checkForUpdates();
});

    7、electron-builder 解決方案(項目打包、運行包、安裝包、更新、支持多平臺)

A complete solution to package and build a ready for distribution Electron app with 「auto update」 support out of the box

(大體意思 electron-builder一個完整的解決方案,打包和創建一個分發的electron程序與「auto update」支持開箱即用)

經過以上六點知識總結,不難理解electron-builder,這裏附一package.json配置文件,後面博主將抽時間寫一篇關於electron-builder打包、更新更詳細文章

{
  "name": "electron-build",
  "version": "1.6.13",
  "main": "src/main.js",
  "description": "electron-build project",
  "author": "Avenstar",
  "license": "",
  "devDependencies": {
    "electron": "^1.4.15",
    "electron-builder": "^12.3.1"
  },
  "dependencies": {
    "electron-updater": "^1.4.2"
  },
  "scripts": {
    "pack": "electron-builder --dir",
    "build": "electron-builder",
    "dev": "electron src/main.js"
  },
  "keywords": [
    "electron",
    "updater",
    "update",
    "mac",
    "osx",
    "linux",
    "desktop"
  ],
  "build": {
    "appId": "com.cilent.app.electronbuild",
    "productName": "electron-build",
    "directories": {
      "output": "build"
    },
    "files": [
      "src/**/*",
      "node_modules/**/*",
      "package.json"
    ],
    "dmg": {
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "mac": {
      "category": "your.app.category.type",
       "icon": "static/icons/app.icns",
      "target": [
        "zip",
        "dmg"
      ],
      "publish": [
        {
          "provider":"generic",
          "url":"http://www.baidu.com/updates/latest/mac/"
        }
      ]
    },
    "win": {
      "icon": "static/icons/icon.ico",
      "target": [
        "nsis",
        "zip"
      ],
      "publish": [
        {
          "provider":"generic",
          "url":"http://www.baidu.com/updates/latest/win/"
        }
      ]
    },
    "linux": {
      "icon": "static/icons"
    },
    "nsis":{
      "oneClick":true,
      "artifactName":"${productName}-setup-${version}.${ext}"
    }
  }
}

做者:Avenstar

出處:http://www.cnblogs.com/zjf-1992/p/7354931.html

關於做者:專一於前端開發

本文版權歸做者全部,轉載請標明原文連接

資料參考

    https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating

    https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating

    https://changkun.us/archives/2017/03/217/?utm_source=tuicool&utm_medium=referral

    https://github.com/amhoho/electron-cn-docs

    https://segmentfault.com/a/1190000010271226

    https://segmentfault.com/a/1190000004863646

    https://github.com/electron-userland/electron-builder

    https://github.com/Squirrel/Squirrel.Windows

    https://segmentfault.com/a/1190000008287730

相關文章
相關標籤/搜索