TL; DR
- Electronの
autoUpdater
モジュールを使うとMac/Windowsでアプリを自動アップデートさせられる - Mac/Windowsそれぞれ違うアップデートのリリース方法が必要
- Mac: アップデート情報を返すWeb APIを用意する
- Windows: grunt-electron-installer で作ったファイルをS3とかにアップロードする
- あとは
autoUpdater
のAPIを呼び出すだけ
はじめに
Electronには autoUpdater
という、アプリの自動アップデート用モジュールが入っている。これを使うとMac/Windowsでアプリを自動アップデートさせることができる。
Wantedlyが開発しているメッセージングアプリのSyncデスクトップ版では、実際にautoUpdater
を使っているが、Mac/Windowsそれぞれで違うセットアップが必要であったりして意外と使うには手間がかかった。
そこで、ElectronのautoUpdater
を使ってMac/Windows上で実際に自動アップデートを行う方法がどうなるかをまとめてみた。
Mac
MacのautoUpdater
には、内部的にSquirrel.Macが使われている。
アプリを署名する
アプリを Developer ID certificate (iOS開発などでApple Developer Program に登録していれば取得できる) で署名する必要がある。
electron-packagerのオプションでも対応している。
署名しないとアップデートのインストールに失敗する。
アプリ (.app
) をzip圧縮する
.app
を直接zip圧縮する。
zip -r -y myapp-1.0.0.zip myapp.app
Web APIを用意する
Squirrel.Macがアップデートをチェックするのに使うWeb APIを用意する。
アップデートがある場合、レスポンスとして、zipファイルのダウンロードURLとメタデータを返す。
リクエスト例
GET releases.myapp.com/latest?version=1.0.0&platform=darwin
パラメータ等はSquirrel.Macが付加するわけではないので自由 (アプリのバージョンなどを元にする)。
レスポンス例 (アップデートあり)
200 OK
{
"url": "https://url/to/myapp-1.0.1.zip",
"name": "my release",
"notes": "my notes",
"pub_date": "2015-07-01T04:46:15.898Z"
}
レスポンス例 (アップデートなし)
204 No Content
autoUpdater
設定
アップデートチェック用APIのURLをsetFeedURL
で設定する。
const {autoUpdater} = require("electron");
autoUpdater.setFeedURL("https://releases.myapp.com/latest?version=1.0.0&platform=darwin");
Windows
Windows上でのautoUpdater
では Squirrel.Windows が使われているので、それに対応するようアプリをリリースする。
grunt-electron-installer でインストーラとNuGetパッケージ用ファイルをつくる
Squirrel.Windows ではアップロードを確認・ダウンロードするのにNuGetパッケージを使っている。
自前でNuGetパッケージを用意することも出来ると思われるが、 grunt-electron-installer を使うと NuGetパッケージに必要なファイルを自動生成してくれる。
さらに、Atomなどのインストーラと似たようなシンプルでかっこいいインストーラも生成してくれるので便利。
gruntのタスクとして提供されているが、gulpなどから使うことも可能。
この際、(特にproductionでは) Authenticode でコード署名をしておく必要がある。
コード署名をしていないと、アプリがマルウェアに誤判定される・ダウンロードしたインストーラを実行するときに怖い警告が表示される、など様々な面倒なことが起こる。
設定例
'create-windows-installer': {
ia32: {
appDirectory: '/tmp/build/myapp', // electron-packagerなどでパッケージしたアプリのディレクトリ
outputDirectory: '/tmp/build/installer',
authors: 'My App Inc.',
exe: 'myapp.exe'
}
}
生成されるファイル例
RELEASES
: リリース一覧のテキストファイル
Setup.exe
: インストーラ
myapp-1.0.0-full.nupkg
: アップデートのnupkg
アップロード
生成されたRELEASES
/ *.nupkg
ファイルをそのまま (S3などに) アップロードすることで、NuGetパッケージをホストすることになる(らしい)。
なので、必ずしもアップデート用にサーバを用意する必要はない。
autoUpdater
設定
RELEASES
と*.nupkg
ファイルがあるディレクトリをsetFeedURL
で設定する。
const {autoUpdater} = require("electron");
autoUpdater.setFeedURL("https://releases.myapp.com/windows");
autoUpdater
を使う (共通)
リリースしたアップデートを実際にアプリ側で適用するには、autoUpdater
モジュールからアップデート処理を呼び出す必要がある。
checkForUpdates()
autoUpdater.checkForUpdates()
を呼び出すとアップデートがチェックされる。アップデートが見つかった場合 即座に ダウンロードが始まる。
quitAndInstall()
アップデートがあった時、autoUpdater.quitAndInstall()
を呼ぶと即座にアップデートをインストールして再起動できる。 (呼び出さなくてもアプリの次回の起動時に自動的にインストールされる)
イベント
アップデートのチェック結果ごとに "update-available"
、"update-not-available"
、"error"
イベントが来る。
アップデートのダウンロードが終わると"update-downloaded"
イベントが来る。
例
const {autoUpdater} = require("electron");
autoUpdater.setFeedURL(<先ほどのURL>);
autoUpdater.checkForUpdates();
autoUpdater.on("update-downloaded", () => {
index = dialog.showMessageBox({
message: "アップデートあり",
detail: "再起動してインストールできます。",
buttons: ["再起動", "後で"]
});
if (index === 0) {
autoUpdater.quitAndInstall();
}
});
autoUpdater.on("update-not-available", () => {
dialog.showMessageBox({
message: "アップデートはありません",
buttons: ["OK"]
});
});
autoUpdater.on("error", () => {
dialog.showMessageBox({
message: "アップデートエラーが起きました",
buttons: ["OK"]
});
});
まとめ
プラットフォームごとにセットアップをすると、autoUpdater
を使ってクロスプラットフォームなアプリの自動アップデートを実現できる。
正直面倒な手順なので、将来的に改善されるべきだとは思う(特に、プラットフォームごとにやり方が違うのは良くない)。
一旦セットアップしてしまえば、簡単にユーザに最新のアプリを使ってもらうことができるので便利。