Electron – チュートリアルその4 ホットリロードを実現する electron-reload の使い方

目次

概要

前回作成した Electron のサンプルコードでは、main.cjs や index.html を変更した場合、一度アプリを終了し、再度起動する必要がありました。これでは、開発中は不便です。 今回は、ファイルの変更を監視し、変更を検知した場合に自動で再起動を行うライブラリ electron-reload について紹介します。自動で再起動を行うことをホットリロード (hot reload) といいます。

インストール

electron-reload をインストールします。

npm install -D electron-reload

使い方

コード全体は以下を参照ください。

electron-examples/04_electron-tutorial-hot-reload

main.cjs を以下のように変更します。

main.cjs

const { app, BrowserWindow } = require("electron");
const electronReload = require("electron-reload");
const path = require("path");

// 開発環境かどうか
const idDev = !process.env.NODE_ENV || process.env.NODE_ENV === "development";

const createWindow = () => {
  const win = new BrowserWindow();
  win.loadFile("index.html");

  if (idDev) {
    // パッケージ化されていない場合
    const electronPath = path.join(
      __dirname,
      "node_modules",
      ".bin",
      "electron" + (process.platform === "win32" ? ".cmd" : "")
    );

    electronReload(__dirname, {
      electron: electronPath,
      forceHardReset: true,
    });
  }
};

app.whenReady().then(createWindow);

変更点は、以下です。 開発環境かどうかを const idDev = !process.env.NODE_ENV || process.env.NODE_ENV === "development"; で判定し、開発環境の場合は、electronReload(paths, options) を呼び出し、ホットリロードを設定します。 electronReload()paths には、監視対象のファイルまたはディレクトリを指定します。options には、Electron の実行ファイルのパスなどを設定します。

// node_modules にインストールされている Electron の実行ファイルのパス
// Windows の場合、node_modules/.bin/electron.cmd にある
const electronPath = path.join(
  __dirname,
  "node_modules",
  ".bin",
  "electron" + (process.platform === "win32" ? ".cmd" : "")
);

electronReload(__dirname, {
  electron: electronPath,
  forceHardReset: true,
});

options に指定できるパラメータ

  • forceHardReset: デフォルトでは、エントリポイントのファイル main.cjs が変更された場合のみ、ホットリロードが実行され、index.html など他のファイルの変更では再起動が行われません。forceHardReset: true を指定することで監視対象のすべてのファイルが変更された場合、再起動するようになります。

TypeScript で使用する場合

1. main.ts を変更する

Typescript で Electron を使用する場合、実際に実行されるのは、main.ts ではなく、tsc コマンドでコンパイル後に出力される ./build/main.js であるため、Electron の実行ファイルの相対パスを指定する際の起点が変わります。

electron-examples
├── build
|  └── main.js
├── index.html
├── main.ts
├── package-lock.json
├── package.json
└── tsconfig.json

main.ts

import { app, BrowserWindow } from "electron";
import * as path from "path";

// 開発環境かどうか
const idDev = !process.env.NODE_ENV || process.env.NODE_ENV === "development";

const createWindow = () => {
  const win = new BrowserWindow();
  win.loadFile("index.html");

  if (idDev) {
    // バイナリ化されていない場合
    const electronPath = path.join(
      __dirname,
      "..",
      "node_modules",
      ".bin",
      "electron" + (process.platform === "win32" ? ".cmd" : "")
    );

    require("electron-reload")(__dirname, {
      electron: electronPath,
      forceHardReset: true,
    });
  }
};

app.whenReady().then(createWindow);

2. package.json のコマンドを変更する

.ts ファイルが変更された場合に、ホットリロードを実現するには、以下の2段階の手順を踏む必要があります。

  1. main.ts が変更されたら、自動で tsc によるコンパイルを行い、./build/main.js を出力する
  2. ./build/main.js が変更されたら、electron-reload によるホットリロードを行う

1に関しては、tsc コマンドを実行する際に -w オプションを使用すると、コンパイル対象のファイルが変更された場合に自動で再コンパイルが行われます。 ただし、tsc -p . -w && electron . としても tsc -p . -w で処理が止まってしまうため、これら2つのコマンドは並列して実行する必要があります。 そのため、concurrently というライブラリをインストールします。

npm install -D concurrently

concurrently は、引数にコマンドを複数渡すと、それらを並列で実行してくれます。 よって、npm start 時のコマンドは、tsc -p . -w\" \"tsc -p . && electron .\" になります。 並列実行のため、コンパイル後に electron コマンドを実行することを保証するため、 tsc -p . && electron . として最初に1回コンパイルしてから electron コマンドを実行しています。

package.json

{
  "name": "electron-example",
  "version": "1.0.0",
  "description": "Electron example",
  "main": "./build/main.js",
  "scripts": {
    "start": "concurrently \"tsc -p . -w\" \"tsc -p . && electron .\""
  },
  "author": "papillon",
  "license": "MIT",
  "devDependencies": {
    "concurrently": "^8.2.2",
    "electron": "^28.1.3",
    "electron-reload": "^2.0.0-alpha.1",
    "typescript": "^5.3.3"
  }
}

コメント

コメントする

目次