🌊

Electronでインストールプロセスをカスタムしてみる

2024/02/03に公開1

Electronのプロジェクトにおいて、インストール時の挙動(任意のファイルをコピーする等)をカスタマイズする方法についてまとめました。
方法はいくつかあると思いますが、パッケージングツールにelectron-forgeとelectron-builderを使用する場合についてです。

electron-forge の場合

afterExtract Hookを使います。
package.jsonまたはforge.config.jsでスクリプトファイルのパスを設定し、指定したファイルにコードを書きます。

packge.jsonでの設定

config.forgeにafterExtract Hookを設定する

"config": {
    "forge": {
      "packagerConfig": {},
      "makers": [],
      "hooks": {
        "afterExtract": [
          "./after-extract-script.js" // 任意のパスを指定
        ]
      }
    }
  },

スクリプトを書く

./after-extract-script.jsにスクリプトを記述

// after-extract-script.js

/**
 * @param {string} buildPath: インストール時にソースコードが展開されるパス
 * @param {string} electronVersion: Electron version
 * @param {string} platform: OS platform (win32等)
 * @param {string} arch: CPU architecture (x86等)
 * @callback done: 処理が完了したことを知らせるcallback関数
*/
module.exports = (buildPath, electronVersion, platform, arch, done) => {
    console.log(`Electronバイナリが展開されました: ${buildPath}`);
    console.log(`Electronのバージョン: ${electronVersion}`);
    console.log(`プラットフォーム: ${platform}`);
    console.log(`アーキテクチャ: ${arch}`);

    // 処理を追加
    // ex) 展開されたディレクトリ内のファイル構造を変更する、特定のファイルやフォルダを追加・削除するするなど

    done(); // 処理が完了したことを知らせる
};

electron-builderの場合

afterPackを使います。electron-forgeと基本的なやり方は同じです。package.jsonまたはelectron-builder.ymlでスクリプトファイルのパスを設定し、指定したファイルにコードを書きます。

electron-builder.ymlでの設定

appId: your.app.id
mac:
  target: dmg
win:
  target: nsis
linux:
  target: AppImage
afterPack: "./scripts/afterPack.js" # 任意のパスを指定

スクリプトを書く

./scripts/afterPack.jsにスクリプトを記述。
試しにフォルダを追加してみます。

const path = require('path');
const fs = require('fs-extra'); // fsでもOK

/**
 * @param {AfterPackContext} context
 * @return {Promise<any> | any}
 * */
module.exports = async (context): => {
  const { appOutDir, electronPlatformName, packager } = context;
  console.log(`Packaging done for ${electronPlatformName} to ${appOutDir}`);

  // 処理を追加
  // ex) extra-folderをappOutDir/resourcesにコピーする
  const extraResourcePath = path.join(__dirname, 'extra-folder');
  const destinationPath = path.join(appOutDir, 'resources', 'extra-folder');

  await fs.copy(extraResourcePath, destinationPath);
};

まとめ

インストールプロセスのカスタムについての日本語記事が少なったので、まとめてみました。
インストーラー実行時の処理を追加できます。私はバックエンドでPythonなどを使っているときに、仮想環境のフォルダをコピーするのに使っています。
参考になれば幸いです。

参考

https://www.electronforge.io/config/hooks
https://www.electron.build/includes/hooks.html#afterpack

Discussion

kako-junkako-jun

本文に「インストール時の挙動」とありますが、
https://www.electron.build/configuration/configuration.html
を読む限り、これは「インストール時の挙動」ではないと思います。

afterPack - The function (or path to file or module id) to be run after pack (but before pack into distributable format and sign).

という説明によれば、「インストーラ作成完了時(Pack時)の挙動」と考えられます。
実際、afterPackに与えたjsファイルは、
electron-builderコマンドによってインストーラのexeが作成される直前に、実行されました。

似た設定値として、afterExtract というのもありますが、

The function (or path to file or module id) to be run after the prebuilt Electron binary has been extracted to the output directory

なので、この実行タイミングはもっと前であり、
Packするためのファイルたちを、準備用の場所に1回展開した時に実行されるようです。

上記を踏まえると、ユーザー環境でのインストールプロセス
(インストーラを実行した時に、postflight的に実行させたい処理)を書くことは、
electron-builderの機能としてはサポートされておらず、
nsisの installer.nsh(仮) の機能として書くしかないのではないでしょうか。