Electron-vue開發實戰4——經過CI發佈以及更新的方式

前言

前段時間,我用electron-vue開發了一款跨平臺(目前支持Mac和Windows)的免費開源的圖牀上傳應用——PicGo,在開發過程當中踩了很多的坑,不只來自應用的業務邏輯自己,也來自electron自己。在開發這個應用過程當中,我學了很多的東西。由於我也是從0開始學習electron,因此不少經歷應該也能給初學、想學electron開發的同窗們一些啓發和指示。故而寫一份Electron的開發實戰經歷,用最貼近實際工程項目開發的角度來闡述。但願能幫助到你們。html

預計將會從幾篇系列文章或方面來展開:前端

  1. electron-vue入門
  2. Main進程和Renderer進程的簡單開發
  3. 引入基於Lodash的JSON database——lowdb
  4. 跨平臺的一些兼容措施
  5. 經過CI發佈以及更新的方式
  6. ...(想到再寫)

說明

PicGo是採用electron-vue開發的,因此若是你會vue,那麼跟着一塊兒來學習將會比較快。若是你的技術棧是其餘的諸如reactangular,那麼純按照本教程雖然在render端(能夠理解爲頁面)的構建可能學習到的東西很少,不過在main端(electron的主進程)應該仍是能學習到相應的知識的。vue

若是以前的文章沒閱讀的朋友能夠先從以前的文章跟着看。node

LOGO的準備

通過前面幾篇文章的實戰,我相信你們已經對於構建一個基本的electron應用沒有太多的問題了。本文主要闡述一下如何讓咱們的應用經過CI系統來自動幫咱們構建應用,而後發佈給用戶使用。以及以後若是有更新,要如何通知用戶更新。react

固然,在此以前,咱們還須要作一件事:給你應用加上好看的LOGO。LOGO的設計和製做不在本文的設計範圍內。爲了咱們的應用可以跨平臺地使用,不一樣平臺上應用的LOGO尺寸和格式也不盡相同。三個平臺所需的圖片格式以下:linux

  • Linux - png
  • macOS - icns
  • Windows - ico

準備一張1024*1024如下,256*256以上(長寬一致)的png圖片,(推薦512 * 512)而後咱們能夠用一些工具來實現從png到其餘兩種格式。搜索png轉ico或者png轉icns的話有不少在線轉換的網站,能夠去上面在線轉換。在mac上我推薦用的是image2icon這個工具。ios

而後咱們將所得的三個圖片文件,放到electron-vue項目根目錄的build/icons/目錄下。git

不一樣平臺的構建配置

本文咱們主要採用electron-vue已經配置好的基於electron-builder的構建腳原本進行咱們的應用構建。構建腳本會讀取package.json裏的build字段裏的配置來進行構建。electron-vue默認的配置以下:github

"build": {
  "productName": "ElectronVue",
  "appId": "org.simulatedgreg.electron-vue",
  "dmg": {
    "contents": [
      {
        "x": 410,
        "y": 150,
        "type": "link",
        "path": "/Applications"
      },
      {
        "x": 130,
        "y": 150,
        "type": "file"
      }
    ]
  },
  "directories": {
    "output": "build"
  },
  "files": [
    "dist/electron",
    "node_modules/",
    "package.json"
  ],
  "mac": {
    "icon": "build/icons/icon.icns"
  },
  "win": {
    "icon": "build/icons/icon.ico"
  },
  "linux": {
    "icon": "build/icons"
  }
}
複製代碼

簡單講述一下build配置裏的一些字段的含義。docker

首先productName是你的應用的名字。appId的做用是用於Windows平臺區分應用的標識。(注意該配置必須配置,並且稍後會有使用該配置的地方。若是不配置不使用的話,構建出來的Windows平臺的應用將沒法發送eletron的桌面通知)dmg這個配置裏描述了macOS平臺裏,打開dmg安裝包後顯示的界面裏的信息。以下圖:

表示了有兩個標識,一個是應用文件,座標是(130, 150), 一個是應用文件夾的快捷方式,座標是(410, 150)

directoriesoutput字段是你應用打包完生成的文件放置的目錄。

files指明瞭要打包的目錄。

macwinlinux是針對三個平臺的不一樣的配置了。能夠看出默認的配置裏對它們的配置都是指向了不一樣的icon圖標(也就是上一節所說的LOGO)。

PicGo在實際開發中,針對一些狀況對默認的build配置項作出了一些增改:

"build": {
  "productName": "PicGo",
  "appId": "com.molunerfinn.picgo",
  "directories": {
    "output": "build"
  },
  "files": [
    "dist/electron/**/*"
  ],
  "dmg": {
    "contents": [
      {
        "x": 410,
        "y": 150,
        "type": "link",
        "path": "/Applications"
      },
      {
        "x": 130,
        "y": 150,
        "type": "file"
      }
    ]
  },
  "mac": {
    "icon": "build/icons/icon.icns",
    "extendInfo": {
      "LSUIElement": 1
    }
  },
  "win": {
    "icon": "build/icons/icon.ico",
    "target": "nsis"
  },
  "nsis": {
    "oneClick": false,
    "allowToChangeInstallationDirectory": true
  },
  "linux": {
    "icon": "build/icons"
  }
},
複製代碼

因爲PicGo在macOS上主要是一個頂部欄應用,因此在底部docker欄我並不想擁有一個佔位的圖標,因此在mac字段里加入了:

"extendInfo": {
  "LSUIElement": 1
}
複製代碼

這個屬性。參考相關issue

在Windows平臺上,默認打包出來的安裝包並無辦法選擇安裝的路徑,只會默認裝到C盤的用戶目錄。這個並非咱們想要的。咱們想要的是讓用戶本身選擇安裝的路徑。

因此須要修改windows的一些配置以及加上一個nsis的配置來實現:

"win": {
  "icon": "build/icons/icon.ico",
  "target": "nsis"
},
"nsis": {
  "oneClick": false,
  "allowToChangeInstallationDirectory": true
}
複製代碼

因爲目前我尚未打包過Linux平臺的應用,因此Linux相關的配置暫時先不作修改。

Windows平臺打包的一個小坑

還記得前面說到的一個配置:appId麼,這個配置須要咱們在主進程index.js裏也要使用。不然打包後的應用將失去Windows平臺的應用通知功能。這個appId是能夠任意取的,只要保證不和其餘應用重複便可。對於PicGo而言,appIdcom.molunerfinn.picgo

打開你的main/index.js,在Windows平臺的時候加上這個appId

// ...
import pkg from '../../package.json'

// ...
// ...

if (process.platform === 'win32') {
  app.setAppUserModelId(pkg.build.appId)
}
複製代碼

這樣就解決了通知的那個問題。

經過CI系統自動構建與發佈

版本相關

發佈應用實際上是一個比較繁瑣的活,每每跟你的版本控制綁在一塊,因此一般在項目開始的階段就要有所佈局。我說說個人作法吧,不必定很科學,不過簡單易行。

  1. 倉庫主要兩個分支,一個dev一個master。平時在dev上開發,只有在發佈新版的時候merge到master上。
  2. 書寫簡單的更新版本的腳本,一鍵打tag+push到GitHub。
  3. 結合CI系統,自動構建master分支的代碼,並將應用推送到GitHub倉庫去。

其中簡單的更新版本的腳本我是在package.json裏寫了簡單的scripts

"scripts": {
  "patch": "npm version patch && git push origin master && git push origin --tags", // 小版本
  "minor": "npm version minor && git push origin master && git push origin --tags", // 次版本
  "major": "npm version major && git push origin master && git push origin --tags"  // 大版本
}
複製代碼

裏面用到了npm的一個命令,npm version [options],具體能夠參考version的文檔。簡單來講,它可以自動幫你升級版本,修改package.json裏的version,並打上相應的git tag,很方便。

舉個例子,一個符合語義的版本號一般由以下三個部分組成:major.minor.patch,好比1.5.3。若是我運行了npm run patch,那麼將會將小版本更新:1.5.4,同時修改package.json裏的version字段爲1.5.4並自動打上一個git tag 1.5.4,並將這個修改和tag推送到遠端。

不過須要注意的是,一開始我是經過electron-vue自帶的npm run build這個腳本讓CI去執行構建,可是發現沒法自動上傳到GitHub的release裏。因此經過查閱相關資料後,發現最簡單的就是把對應的npm scripts命名爲release。因而我把本來的npm run build的腳本複製了一遍,起了一個新名release:

"scripts": {
  // ...
  "release": "node .electron-vue/build.js && electron-builder",
  // ...
}
複製代碼

CI相關

說到這裏都還沒說到CI系統。什麼是CI?能夠參考阮一峯老師給出的解釋《持續集成是什麼?》。咱們若是每次發佈應用都須要咱們在本地構建,而後手動上傳到GitHub(或者其餘地方)去,而後讓別人能下載的話,未免太累了。並且一般咱們開發electron應用就是爲了可以跨平臺,可是要構建不一樣的平臺的應用意味着咱們要在不一樣的平臺分別構建。這也是不能忍受的。

因而網上有一些第三方的CI系統,它們可以幫咱們,在某些分支(好比master)發生了某些更新(好比更新了tag)的時候幫咱們執行某些腳本(好比構建、測試)。這樣就省卻了咱們在本地、多平臺構建的煩心事,並且讓一些都變得「自動化」了起來。

有了CI以後,個人electron應用的發佈就變成這樣的流程了:

這樣,咱們只須要Push代碼足矣。

針對Linux或者macOS的構建,咱們可使用Travis-CI,針對Windows平臺的構建,咱們可使用AppVeyor。一個好消息是,它們對於在GitHub上的開源項目都是能夠免費構建的,而且和GitHub的倉庫結合地特別好,配置也比較簡單,能夠說的很是良心了。

在使用它們以前,咱們須要給予它們必定的權限讓它們可以訪問咱們的GitHub倉庫。因此須要:

  1. 用你的GitHub帳號註冊它們,才能獲取你的倉庫列表。
  2. 在GitHub上生成token,賦予CI系統讀寫你的倉庫的權限。生成token的具體操做能夠查看以前我寫的一篇針對hexo持久化構建的文章
  3. 針對不一樣的CI平臺建立不一樣的配置文件,好讓它們知道你要它們執行什麼操做。不過electron-vue很友好地爲咱們準備了Travis-CI的配置文件模板.travis.yml和AppVeyor的配置文件模板appveyor.yml。因此咱們基本上只須要在它們的基礎上小修改便可。

Travis-CI

註冊並登陸Travis-CI後,找到你要構建的倉庫,而後打開,點擊設置進入以下頁面:

配置一下環境變量,名爲GH_TOKEN,token的值就是上一步咱們在GitHub生成的token。等會會有用。

PicGo通過修改後的.travis.yml以下:

# Commented sections below can be used to run tests on the CI server
# https://simulatedgreg.gitbooks.io/electron-vue/content/en/testing.html#on-the-subject-of-ci-testing
osx_image: xcode8.3
sudo: required
dist: trusty
language: c
matrix:
 include:
 - os: osx
  # - os: linux
 env: CC=clang CXX=clang++ npm_config_clang=1
 compiler: clang
cache:
 directories:
 - node_modules
 - "$HOME/.electron"
 - "$HOME/.cache"
addons:
 apt:
 packages:
 - libgnome-keyring-dev
 - icnsutils
before_install:
- mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
  "$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
  | tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull install:
- nvm install 8.9
- curl -o- -L https://yarnpkg.com/install.sh | bash - source ~/.bashrc - npm install -g xvfb-maybe - yarn script:
- npm run release
- yarn run build:docs
branches:
 only:
 - master
after_script:
 - cd docs/dist
 - git init
 - git config user.name "Molunerfinn"
 - git config user.email "marksz@teamsz.xyz"
 - git add .
 - git commit -m "Travis build docs"
 - git push  --force --quiet "https://${GH_TOKEN}@github.com/Molunerfinn/PicGo.git" master:gh-pages
複製代碼

拋去不少前置依賴(好比C++編譯庫之類的)和構建環境(是什麼系統,是什麼語言),那些都是electron-vue給咱們預置好的。咱們須要注意的僅僅是幾個部分:

  1. script
  2. branches
  3. after_script

script是當系統和環境和依賴都準備好以後,你要CI運行的命令。在這裏我運行了兩個命令,一個是npm run release,這個就是打包構建應用啦,而且執行了這個命令以後,electron-builder會自動將生成好的安裝包推送到咱們GitHub倉庫的draft release裏。另外一個是構建PicGo主頁的命令yarn run build:docs

branches聲明瞭你要在哪些分支在GitHub接收到了代碼更新以後就構建,這裏咱們天然選擇的是master。

after_script是當你執行完script裏的腳本以後要作的事。能夠爲空。對於我而言主要在這個部分將上一步構建好的PicGo主頁推送到GitHub的gh-pages分支。固然若是你的應用有使用說明、文檔之類的網站,也能夠在這裏進行構建和推送。

注意到,在after_script命令的最後一行,有個${GH_TOKEN},這個就是咱們以前在Travis-CI配置裏配置的環境變量GH_TOKEN。用環境變量的好處是不會暴露你的TOKEN,只有構建系統知道。

AppVeyor

有了以前的經驗,AppVeyor就更簡單了。註冊登陸後,咱們在主頁添加一個PROJECT,選中你要構建的倉庫。而後找到SETTING設置:

而後在左側的Genral一欄的內容區中,找到構建的分支爲master,以及設置咱們僅在tag更新的時候構建:

固然這個都是根據項目實際來的配置,我只是說PicGo的項目是這樣配置的。

而後在左側的Environment區,找到環境變量配置,咱們依然寫入GH_TOKEN:

修改完配置都別忘了拉到底部去保存!

這樣就算配置完了網頁端的。而如今咱們來看看appveyor.yml這個配置文件:

# Commented sections below can be used to run tests on the CI server
# https://simulatedgreg.gitbooks.io/electron-vue/content/en/testing.html#on-the-subject-of-ci-testing
version: 0.1.{build}

branches:
 only:
 - master

image: Visual Studio 2017
platform:
 - x64

cache:
 - node_modules
 - '%APPDATA%\npm-cache'
 - '%USERPROFILE%\.electron'
 - '%USERPROFILE%\AppData\Local\Yarn\cache'

init:
 - git config --global core.autocrlf input

install:
 - ps: Install-Product node 8 x64
 - git reset --hard HEAD
 - npm install
 - node --version

build_script:
  #- yarn test
 - npm run release

test: off
複製代碼

依然是隻須要關注咱們所關心的配置便可。一個是branches,一個是build_script。有了Travis-CI.travis.yml的經驗,我相信你也能很快理解它。

通過上述配置以後,你已經實現了一個簡單的前端工程的自動化構建推送流程了。而今你只須要關注代碼提交,應用的構建都將會由CI系統自動幫你完成。固然CI系統也不只僅是拿來構建electron應用的,正如你所見的,你能想到的其餘項目的構建、測試其實它都能幫你經過預約義好的腳本完成。

發佈Release

當CI構建玩應用,會將其推送到你的GitHub的release頁面成爲一個draft(草稿),你能夠編輯這個草稿,加上標題和更新說明,就能夠點擊publish發佈你的新版本的應用啦。

electron應用的更新

electron應用的自動更新其實社區有很好的解決方案electron-updater。而electron-vue也在主進程的main/index.js裏預先幫咱們寫好了一段註釋的代碼:

// import { autoUpdater } from 'electron-updater'

// autoUpdater.on('update-downloaded', () => {
// autoUpdater.quitAndInstall()
// })

// app.on('ready', () => {
// if (process.env.NODE_ENV === 'production') {
// autoUpdater.checkForUpdates()
// }
// }
複製代碼

只要引入autoUpdater就能自動幫咱們檢查更新和自動下載安裝更新。不過,凡事都有不過。這個方式雖然很簡單,可是它須要的條件比較嚴格,須要你擁有證書用於應用簽名。而macOS平臺下的證書須要你申請開發者,一年99$的費用讓我望而卻步。

因而我只能退而求其次,能不能經過查詢GitHub的release版本號,來比對當前版本,是否須要更新,並提醒用戶呢?通過嘗試,發現可行。個人實現方法以下:

我首先寫了一個updateChecker的助手:

import { dialog, shell } from 'electron'
import db from '../../datastore'
import axios from 'axios'
import pkg from '../../../package.json'
const version = pkg.version
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'

const checkVersion = async () => {
  let showTip = db.read().get('picBed.showUpdateTip').value()
  if (showTip === undefined) {
    db.read().set('picBed.showUpdateTip', true).write()
    showTip = true
  }
  // 自動更新的彈窗若是用戶沒有設置再也不提醒,就能夠去查詢是否須要更新
  if (showTip) {
    const res = await axios.get(release)
    if (res.status === 200) {
      const latest = res.data.name // 獲取版本號
      const result = compareVersion2Update(version, latest) // 比對版本號,若是本地版本低於遠端則更新
      if (result) {
        dialog.showMessageBox({
          type: 'info',
          title: '發現新版本',
          buttons: ['Yes', 'No'],
          message: '發現新版本,更新了不少功能,是否去下載最新的版本?',
          checkboxLabel: '之後再也不提醒',
          checkboxChecked: false
        }, (res, checkboxChecked) => {
          if (res === 0) { // if selected yes
            shell.openExternal(downloadUrl)
          }
          db.read().set('picBed.showUpdateTip', !checkboxChecked).write()
        })
      }
    } else {
      return false
    }
  } else {
    return false
  }
}

// if true -> update else return false
const compareVersion2Update = (current, latest) => {
  const currentVersion = current.split('.').map(item => parseInt(item))
  const latestVersion = latest.split('.').map(item => parseInt(item))
  let flag = false

  for (let i = 0; i < 3; i++) {
    if (currentVersion[i] < latestVersion[i]) {
      flag = true
    }
  }

  return flag
}

export default checkVersion
複製代碼

而後在main/index.js裏,我在app準備啓動的時候,調用這個更新助手:

// ...
import uploader from './utils/uploader.js'

app.on('ready', () => {
  // ...
  updateChecker()
  // ...
})
複製代碼

這樣就能在啓動應用的時候彈出更新提示:

總結

本文簡要地講述了electron應用用上CI系統幫咱們自動化構建和推送,以及在沒有申請開發者,沒有證書用於應用的代碼簽名的狀況下如何告知用戶進行應用更新。要作一個健壯的應用就應該考慮到應用的版本發佈、版本更新和對用戶的更新通知。

本文不少都是我在開發PicGo的時候碰到的問題、踩的坑。也許文中簡單的幾句話背後就是我無數次的查閱和調試。但願這篇文章可以給你的electron-vue開發帶來一些啓發。文中相關的代碼,你均可以在PicGo的項目倉庫裏找到,歡迎star~若是本文可以給你帶來幫助,那麼將是我最開心的地方。若是喜歡,歡迎關注個人博客以及本系列文章的後續進展。

注:文中的圖片除未特意說明以外均屬於我我的做品,須要轉載請私信

相關文章
相關標籤/搜索