JavaScript
Electron

Electronの簡易アップデート機能を実装した話

こんにちは、Ducklings@syumaiです。会社では、360°映像 x ウェディングのサービス、HUG WEDDINGの開発をやっています。
エンジニアは二人で、RailsやVue.jsを使った開発を基本的に行っています。(直近はC#をひたすら書いてました)

Electron使ってます

弊社で作っている社内ツールに、Electronを使用しているものがいくつかあります。

Electronを採用した目的としては、
アルバイトの方などのコマンドラインツールに親しみが無いメンバーにも簡単に使ってもらえるように、
Node.jsツールのフロントエンドを提供する事が主となります。

Web用のUIライブラリも簡単に使えるし、
過去に別の目的で作った社内JSライブラリ等を持って来て使い回せているので、開発がめちゃめちゃ楽です。
Electron最高…。

今回やりたかったこと

社内ツールのアップデートを自動で行いたい

  • 会社のスタッフが、東京、大阪、名古屋と散らばっているので、いちいちツールの再配布や連絡を行うのが面倒。
  • 使用するスタッフが気付かないうちに、サクッとアップデートが行われるのが理想的。

フロント側のコードだけアップデートしたい

  • 基本的に、フロントのコードだけがアップデートされればいい。
  • フォントや画像などのアセットも基本的に更新しない。
  • フロントのコードのみなら、数100kBになるので、アップデートの負荷が低い。

と言うことで…、

ストアに出すアプリケーションでも無いし、
上記の目的のために、Squirrelを使うのも大げさな感じがしたので、
フロントのコードだけを差し替える仕組みを整えました。

実装方針

  • メインプロセスのコード、フロントのコード、その他アセットをそれぞれ別のasarとして固めるようにする
  • アップデート機能は全てメインプロセス側に載せる
  • アプリケーションの起動時にアップデートをチェックし、アップデートがあればダウンロードする
    • アップデート対象のファイルは、フロントのコードのみ
  • 起動時に、アップデートのファイルが存在すれば、現在のフロントのasarと差し替える

実装のポイント

Electronアプリケーション起動中のasar差し替え

基本的に、asarはElectronアプリケーション起動中に差し替えられる事を想定していません。

Replacing the asar file when app is running will never be supported in Electron, it is like replacing the .exe or .dll when the program is running, which is very likely to cause troubles.
https://github.com/electron/electron/issues/2198#issuecomment-121730822

一度展開された後に、無理矢理asarを差し替えた場合、メインプロセスが落ちます。

asarの展開のタイミングは、asarパッケージ内のファイルへアクセスしようとするタイミングです。
fsや、html内からのアセット読み込みで使用しようとした時に展開されるようです。

なので、フロントのコードが読み込まれる前にアップデート作業を完了する必要があります。

original-fsを使う

Electronに付属のfsは、asarをただのディレクトリかのように扱えるようカスタマイズされています。
https://github.com/electron/electron/blob/master/docs/tutorial/application-packaging.md
なので、fs.rename('hoge.asar')などでファイルを移動しようとすると失敗します。

こういったケースのために、

  • const originalFs = require('original-fs');
  • process.noAsar = true;

などで、asarを通常のファイルと同じように扱う手段が提供されているので、これらを使いましょう。

ビルド時にうまくasarを分ける

ビルドにはelectron-packagerを使っていますが、electron-packagerの--asarオプションを使うと、全てのコードが一つのasarにパッケージングされてしまいます。
今回は、メインプロセスと、フロントのコードを別々にパッケージングしたいので、
アプリケーションのビルド時に、asar packコマンドでフロントのコードを別でパッケージングし、Electronのresourcesディレクトリ配下にコピーされるように設定します。

実装内容

時間が出来たらリポジトリ作って載せます…!汗

結果

うまく、スタッフに気付かせないようサクッとアップデートする仕組みが完成しました!
これからもガンガンElectron使っていきます!