技術ログ

Electronアプリの自動アップデート機構を作る (実装記)

公開: 2026-05-19 · 著者: Sasaki Ryuji

Electron配布で「ユーザーに古いバージョンを使わせ続けない」ための仕組みを実装する

Electronアプリの自動アップデート機構を作る (実装記)

あなたがElectronで配布しているデスクトップアプリに、自動アップデート機構を入れていますか?もし入っていないなら、ユーザーから「動かない」「バグがある」と言われたときに、実は数バージョン前を使っていただけだった、というケースが頻発しているはずです。GramShift Desktopは現在までに17回リリースしていますが、自動アップデート機構を最初から入れたことで、サポート対応時間を明確に削減できました。この記事では実装の核と、私が踏み抜いた具体的な落とし穴を共有します。

構成全体像: electron-updater + GitHub Releases

GramShift Desktop の自動アップデート機構は、electron-updaterパッケージと GitHub Releases を組み合わせた標準的な構成です。新しいバージョンをリリースする手順はこうなります。第一に、ローカルで npm version patch/minor/major でバージョンを上げる。第二に、npm run build で各プラットフォーム向けインストーラーを生成。第三に、GitHub Releases に .exe / .dmglatest.yml をアップロード。第四に、起動済みクライアントが定期的に latest.yml をチェックして、新バージョンを検出すると自動でダウンロード・インストールします。

この構成のいいところは、サーバーを別途運用する必要がないことです。GitHub Releases が CDN として機能し、無料で配信できます。GramShift では月間ダウンロード総量が約3GBほどありますが、GitHub の帯域制限に引っかかったことはありません。

main プロセスでの実装最小コード

Electron の main プロセスでの最小限の実装はこのようになります。アプリ起動直後にチェックして、新バージョン検出時にユーザーに通知、ダウンロード後にインストール確認ダイアログを表示する流れです。

const { app, dialog, autoUpdater } = require('electron');
const { autoUpdater: electronUpdater } = require('electron-updater');

function setupAutoUpdate(mainWindow) {
 electronUpdater.autoDownload = false;
 electronUpdater.autoInstallOnAppQuit = true;

 electronUpdater.on('update-available', (info) => {
 dialog.showMessageBox(mainWindow, {
 type: 'info',
 title: '新しいバージョンがあります',
 message: `v${info.version} に更新できます`,
 buttons: ['今すぐ更新', '後で']
 }).then((result) => {
 if (result.response === 0) electronUpdater.downloadUpdate();
 });
 });

 electronUpdater.on('update-downloaded', () => {
 dialog.showMessageBox(mainWindow, {
 title: '更新の準備ができました',
 message: 'アプリを再起動して更新を適用します',
 buttons: ['再起動', '次回起動時']
 }).then((result) => {
 if (result.response === 0) electronUpdater.quitAndInstall();
 });
 });

 electronUpdater.checkForUpdates();
}

app.on('ready', () => {
 const mainWindow = createWindow();
 setupAutoUpdate(mainWindow);
});

autoDownload = false にしているのは、ユーザーの帯域とディスク容量を勝手に消費したくないからです。「更新可能」を伝えてから、ユーザーの同意を得てダウンロードに進むほうが、リアクションも良くなります。

v1.5.7 リリースで踏み抜いた落とし穴 — 難読化の罠

これまで25リリースを重ねた中で最も印象に残っているのが、v1.5.7 リリース時の難読化トラップです。当時、私は配布ファイルの逆コンパイル対策として一部の JavaScript を難読化していたのですが、API 通信を担当する api.js も誤って難読化対象に含めてしまいました。その結果、reportActivity 関数の HTTP 通信だけが本番環境で動かない、という症状が発生しました。

奇妙なことに heartbeatreportStats は同じ api.js から動いていて、ダッシュボードには「今日のいいね 0」と表示されるのに、実際の DB には件数が記録されている、というねじれ状態でした。原因が「特定の関数だけ難読化で名前変換が壊れている」と気づくまで約3時間、ログ追加と検証を繰り返しました。最終的に api.js を難読化対象から外して再ビルドすると、すべての通信が復活しました。

この失敗から得た教訓は「ネットワーク通信を担うファイルは難読化対象から除外する」「リリース直後の数時間は本番ダッシュボードに張り付いて表示の整合性を確認する」の2つです。難読化は逆コンパイル対策として一定の効果がありますが、デバッグ時の難易度を明確に上げるので、対象を絞り込むのが必須です。

コード署名と Windows SmartScreen 警告

Windows でElectronアプリを配布すると、最初の数百ダウンロードの間は SmartScreen の「発行元が確認できません」警告が出ます。コード署名証明書を購入すれば回避できますが、年間 3-5 万円のコストがかかります。個人開発の初期段階では「警告を一旦許容して、後から署名を入れる」という選択でも問題ないと判断しました。GramShift も現状は無署名で、ダウンロード時の警告画面を回避する手順をユーザーマニュアルに記載しています。

ダウンロード総数が1,000を超えると SmartScreen のレピュテーションが上がって警告が出なくなる仕様もあるため、初期 1,000 ダウンロードは「警告を許容しつつ実績を積む」期間として戦略的に運用するのもありです。

自動アップデートは「ユーザー対応コストを削減する投資」

自動アップデート機構の実装には、初期構築で約1日かかります。しかし運用開始後は、ユーザーが古いバージョンを使い続けることがほぼなくなり、サポート対応の前提が揃います。「バグ報告 → どのバージョンですか? → 最新版にしてください → 解決」というルーチンを完全に省略でき、私の場合、月のサポート対応時間が約 40% 削減されました。Electronで個人開発しているなら、リリース第1版から自動アップデートを組み込むことを強くおすすめします。

GramShift Desktop 17リリースの軌跡 (一部抜粋)

自動更新を入れたおかげで、リリースペースが落ちませんでした。代表的なリリースを並べると、改修の方向性が見えます。

  • v1.0.0 (2025年12月): 初版リリース、自動いいね基本機能
  • v1.1.x (2026年1月-2月): 自動フォロー追加、UI改善、JSTタイムスタンプ統一
  • v1.2.0 (2026年4月19日): Intelligent Engagement Update、フォロワー属性に応じた優先度ロジック
  • v1.2.2 (2026年5月4日): エラー耐性 + 監視機能強化、Discord webhook 集約
  • v1.3.0 (2026年5月9日): 検索UI経由フロー大改修、難読化導入
  • v1.5.0 (2026年5月16日): Meta検知対策、Human-Pacing基盤の大幅強化 (詳細閾値は非公開)
  • v1.5.3 (2026年5月16日): キーワード検索フローの全面書き直し、人間風タイピング導入
  • v1.5.4 (2026年5月16日): 競合フォロワーターゲティング機能を完全廃止 (誇大表記リスク・規約グレーゾーン回避)
  • v1.5.5 (2026年5月16日): キーワード枯渇の自動検知 + Discord 通知
  • v1.5.7 (2026年5月17日): 配布周りの設定改善

1日に6リリース連続でぶん回した日 (5/16のMeta検知対応) は、自動更新がなければ配信できませんでした。クライアント側に「今日6回更新してください」と言うわけにはいきません。リリース → 自動更新 → 即反映、のサイクルが回せたから、当日に Human-Pacing を実装〜配信まで完了できました。

個人SaaSの本番運用記録は技術ログ失敗談カテゴリに随時追記しています。