Help us understand the problem. What is going on with this article?

electron-vueで自動アップデートを実装する

More than 1 year has passed since last update.

最近 electron-vue を利用してデスクトップアプリを開発してます。
mac/windows両方のデスクトップアプリが簡単に作れるなんて・・・本当に便利な世の中になりました。
今回はその開発の中で実装した自動アップデート機能について簡単にまとめておきたいと思います。
(mac/windows両者アプリはストア経由での配信ではありません)

自動アップデート自体はElectronのautoUpdaterモジュールを利用します。
MacのautoUpdaterには、内部的にSquirrel.Macが使われており、
Windows上でのautoUpdaterでは Squirrel.Windowsが利用されています。

使うもの

用意しておく環境

  • Github
  • Heroku

Nutsってなに?

アップデート用のサーバになります。
ElectronのautoUpdaterモジュールを利用してMac/Windowsの自動アップデートを実装するわけですが
サーバサイド側のアップデートチェックAPIや、アップデート用ファイルのダウンロードAPIなど、autoUpdaterに対応したサーバを構築するのって手間です。
Squirrel.Macのサーバサポートについて

Nutsはアップデートに必要なAPIをいろいろ用意してくれるサーバを簡単に構築できます。
しかもMac/Windows両方対応。(すごい)

下記画像の通り、Deploy to Herokuボタンで簡単にHerokuデプロイでき、かつGithubと連携させることができるのです。
Githubと連携させるということは、GithubでReleaseしたファイルをアップデート用のファイルとして扱うことができます。

スクリーンショット 2018-07-25 0.41.24.png

デプロイできたらHeroku側の環境変数の設定で
GITHUB_REPO (リリースで使うリポジトリ名)
GITHUB_TOKEN (GithubのPersonal access token)
API_PASSWORD (空でOK)
API_USERNAME (空でOK)

必要項目を入力しておきます。
プライベートリポジトリを対象にできますので安心ですね。

これでNutsのデバック用APIでレスポンスを確認できます。
https://xxxxxxxxxx.herokuapp.com/api/versions
詳しくはドキュメントを参照!
https://nuts.gitbook.com/api.html

Electron側の実装

electron-vueのフォルダ構成に従い下記のようなファイルを作りました。
(src配下には index.jsだったりindex.dev.jsがあります。Electronメインプロセスの処理部分ですね)
(エラー処理とかは省いてます。ソースもサンプルから)

src/autoupdater.js
'use strict';
const os = require('os');
const {app, autoUpdater, dialog} = require('electron');
const version = app.getVersion();
const platform = os.platform() + '_' + os.arch();

const updaterFeedURL = 'https://xxxxxxxx.herokuapp.com/update/' + platform + '/' + version;

function appUpdater() {

    autoUpdater.setFeedURL(updaterFeedURL);
    autoUpdater.on('error', err => console.log(err));
    autoUpdater.on('checking-for-update', () => console.log('checking-for-update'));
    autoUpdater.on('update-available', () => console.log('update-available'));
    autoUpdater.on('update-not-available', () => console.log('update-not-available'));
    autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
        let message = app.getName() + ' ' + releaseName;
        if (releaseNotes) {
            const splitNotes = releaseNotes.split(/[^\r]\n/);
            message += '\n\nリリース内容:\n';
            splitNotes.forEach(notes => {
                message += notes + '\n\n';
            });
        }
        dialog.showMessageBox({
            type: 'question',
            buttons: ['再起動', 'あとで'],
            defaultId: 0,
            message: '新しいバージョンをダウンロードしました。再起動しますか?',
            detail: message
        }, response => {
            if (response === 0) {
                setTimeout(() => autoUpdater.quitAndInstall(), 1);
            }
        });
    });
    autoUpdater.checkForUpdates();

}
exports = module.exports = {
    appUpdater
};

これを同じくsrc配下のindex.jsで呼び出してあげます

src/index.js
import { app, BrowserWindow , Menu} from 'electron'
const {appUpdater} = require('./autoupdater');
const isDev = require('electron-is-dev');
const version = app.getVersion();

省略..........

/**
 * Auto Updater
 *
 * Uncomment the following code below and install `electron-updater` to
 * support auto updating. Code Signing with a valid certificate is required.
 * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
 */

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

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

app.on('ready', () => {
  appUpdater();
})

アプリのバージョン指定はpackage.jsonに記述します。

package.json
{
  "name": "Sample App",
  "version": "3.2.0",
  "author": "testsan",

//余談ですが開発用ビルドでこのバージョンをelectron側で参照しても
//package.jsonで指定したバージョンは取得できません。electron自体のバージョンが表示されます。

electron-vueのsrc/index.jsには元からAuto Updater用のロジックがコメントアウトで記載されてますが
今回はサンプルソースから必要ロジックを記述してるので、その部分はコメントアウトのままです。

実装後、本番用ビルドしたアプリを起動すれば
autoUpdaterのcheckForUpdatesが行われますので、新しいバージョンがあればサーバからファイルダウンロードし
そのあと更新通知のダイアログがでます。

スクリーンショット 2018-07-25 1.23.05.png

(Heroku側のApplication Logsを見ればサーバリクエストの様子がみれます)
(ファイルダウンロード後なので起動してからダイアログがでるまで時間がかかります)
(開発用ビルドのアプリでは確認できません、後述のcode signing)

ビルドについて

上記画像のようなダイアログが表示されるのは、当然ビルドした新しいバージョンのファイルをGithub Releaseしている状態です。
ここではMac用、Windows用のビルドの仕方を紹介します。

Mac

Mac用にビルドしてアプリのファイルを作成するわけですが、
ElectronのautoUpdaterを利用するにはコードサイニングが必要になります。アプリの署名ですね。
Apple Developer Programに登録して
https://developer.apple.com/account/mac/certificate
からCERファイル(証明書ファイル)をダウンロードする必要があります。
CERファイルを作成するにはMacのキーチェーンアクセスから
CSRファイル(CertificateSigningRequest.certSigningRequest)を作成します。
そして最終的には.p12ファイルを書き出すわけです。
electron-vueのビルドにはelectron-builderが使われてますが
electron-builderでコードサイニングを行うには.p12ファイルが必要になります。

では.p12ファイルが作成できたらどのようにしてelectron-builderに指定してあげるのか?

https://www.electron.build/code-signing

上記ドキュメントに書いてありました。
必要な環境変数を設定してあげれば、electron-builderがコードサイニングしてくれます。

export CSC_LINK=~/electron/project/xxxxx.p12 (.p12ファイルの場所)
export CSC_KEY_PASSWORD=xxxxx(.p12書き出すさいに指定したパスワード)
export CSC_IDENTITY_AUTO_DISCOVERY=true (defaultでtrueのはずなのでいらないかも)

macのターミナルで上記を叩くだけです。
そのあとelectron-vueプロジェクト配下で

npm run build

すればビルド時にコードサイニングされ、アプリファイルが出来上がります。

buildフォルダ配下に下記のファイルができあがり。

testapp-3.2.0-mac.zip
testapp-3.2.0.dmg
testapp-3.2.0.dmg.blockmap
mac/testapp.app

Windows

Windowsの場合は、ストア経由でなければWindowsアプリ用の署名は必要ありません。
Windows用にビルドしてファイルを作成するだけです。
Windowsの場合はインストーラのほうがいいので、インストーラ作成の方法を紹介します。
(MacからWindows用のインストーラ作成を前提としています)

使うもの

  • electron-winstaller
npm install --save-dev electron-winstaller

package.jsonと同じ階層に下記ファイルを用意
(electronプロジェクトのパスが/Users/xxxxxxx/electron/project/の場合)

windows-build-installer.js
var winstaller = require('electron-winstaller');

winstaller.createWindowsInstaller({
  appDirectory: '/Users/xxxxxxx/electron/project/build/win-unpacked',
  outputDirectory: '/Users/xxxxxxx/electron/project/build/',
  authors: 'testapp',
  exe: 'testapp.exe'
})
.then(() => console.log('It worked!'))
.catch(e => console.log(`No dice: ${e.message}`));

ビルドする

./node_modules/.bin/build --win --x64

Windows用のビルド、インストーラの作成は色々方法がありますが、
自分は上記ビルドの仕方で落ち着きました。

buildフォルダ配下に下記のファイルができあがり。

win-unpacked/
squireele-windows/
squireele-windows/testapp Setup 3.2.0.exe
squireele-windows/testapp-3.2.0-full.nupkg
RELEASES

Github Release

ビルドして出来上がったアプリファイル(Mac/Windows)をGithub Releaseします。

スクリーンショット 2018-07-25 2.23.16.png

Tag Versionにはpackage.jsonで指定したバージョンを。
Rellease titleは autoUpdaterのreleaseNameになります。
Describe this releaseはautoUpdaterのreleaseNotesになります。

そして ドロップするファイルは

testapp-3.2.0-mac.zip
testapp-3.2.0-full.nupkg
RELEASES

になります。
(RELEASESファイルはWindowsの自動アップデートで必要です。)

リリース後、
https://xxxxxxxxxx.herokuapp.com/api/versions
でレスポンスを確認してみてください。
Nutsはキャッシュがあるようですので、最新の状態にするには
https://xxxxxxxxxx.herokuapp.com/api/refresh
を叩いてキャッシュクリアする必要があります。

これでアプリから自動アップデートのダイアログを表示させることができます。

おわり

以上が"electron-vueで自動アップデートを実装する"でした。
electronは独学だったので、ネットで情報集めるのがとても苦労しました。
(方法が色々あったり、情報が古かったり)
トライアンドエラーですね。。。。

自分はVue.jsが好きなので、ElectronでもVue.jsを使いました。
レンダープロセスで利用するjsフレームワークは他に色々ありますが
自動更新の流れはどれも一緒ですよね。

自分みたいな独学Electron使いの参考になれれば幸いです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away