18
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Electron Tips ~便利なモジュールや小技~

Last updated at Posted at 2022-01-27

Electronを使用した開発を最近行ったので、個人的に便利だったモジュールや小技などをまとめていこうと思います。

使用したElectronのバージョンは15系です。

Electronのメインプロセス側の基本コード

基本のメインプロセスの構成はだいたい誰が書いてもこのようになると思いますので、こちらをベースに紹介していこうと思います。

すべてのプラットフォームで動作する結合絶対パスを作成するためにnode.jsの標準モジュールであるpathを使用しています。

main.js
//だいたいこんな感じ
import path from "path";

let mainWindow;

const createMainWindow = () => {
    mainWindow = new BrowserWindow({
        width: 1200,
        height: 800,
        webPreferences: {
            preload: path.resolve(__dirname, 'preload.js'),
        },
    });

    mainWindow.loadFile(path.resolve(__dirname, 'index.html'));
};

app.on('ready', () => {
    createMainWindow();
});

アプリの二重起動を防止したい

開発するデスクトップアプリによっては、アプリの複数起動を避けたい場合もあると思います。

requestSingleInstanceLock()というメゾットでアプリケーションのインスタンスのロックが成功したかどうかが分かります。(ドキュメント)
ロックに失敗した場合(falseの場合)、すでにこのアプリのインスタンスがロックされているということなので、既にアプリが起動しているかどうかを検知することができます。

main.js
const createMainWindow = () => {
    // 省略
};

const gotTheLock = app.requestSingleInstanceLock();

// false(既に起動)の場合 即終了
if (!gotTheLock) {
  console.log("二重起動ストップ!! 即停止!!");
  app.quit();
}

// true(初回起動)の場合
app.on('ready', () => {
    createMainWindow();
});

開発時にホットリロードさせたい

開発時にソースコードを変更するたびに、アプリを落として再実行するのはかなり面倒くさいですよね。
electron-reloadというライブラリを使えば簡単にホットリロード設定が可能です。

main.js
const  electronReload  =  require('electron-reload')
//環境変数で開発環境かどうかをチェック
const isDev = process.env.NODE_ENV === 'development';

// macとwinでElectron実行のPATHが違う
const execPath =
    process.platform === 'win32'
        ? '../node_modules/electron/dist/electron.exe'
        : '../node_modules/.bin/electron';

if(isDev) {
    electronReload(__dirname, {
        electron: path.resolve(__dirname, execPath)
    });
}

OS起動時・ログイン時にアプリも自動起動させたい

常駐するアプリなどを実装する際,OSの起動やログイン時にアプリも一緒に起動させたい場合もあると思います。

そのような場合、auto-launchというモジュールを使うことによって、Windowsやmacの起動時に自動でアプリを起動するように「レジストリ」や「ログイン項目」に登録することができます。

npm install --save auto-launch
main.js
import AutoLaunch from "auto-launch";

//環境変数で開発環境かどうかをチェック
const isDev = process.env.NODE_ENV === 'development';

const launch = new AutoLaunch({ name: "your-app-name" });
// 即実行
(async () => {
 // 自動起動アプリとして登録されているかチェック(Promiseで返ってくる)
  const isEnabled = await launch.isEnabled();
// 本番環境かつ自動起動アプリとして登録されていない場合、レジストリ等に登録
  !isDev && !isEnabled && launch.enable();
})();

const createMainWindow = () => {
  // 略
}

// 略

開発環境で auto-launch を登録してしまうと空のelectronアプリが登録されてしまうので、環境変数などで本番環境でのみ動作するように気をつけましょう。

リンクをふんだらブラウザに飛ばしたい

Electron上でURLのリンクを踏むと、Electronで別ウィンドウが立ち上がり、そこでページが開かれてしまいます。

Electronがリンクを開くときに発生するイベントには2種類あり、リンクをクリックしたときに発生するwill-navigate、**target="_blank"**などで新しいウィンドウを開こうとするときに発生するnew-windowの両方の処理にハンドラをかませます。

shell.openExternalはElectronの標準のモジュールで、URLを既定のブラウザで開くことができます。
(特定のページはElectronで開きたい!!みたいな場合はif文やswitch文で条件分岐させるとよいと思います)

main.js

const createMainWindow = () => {
    mainWindow = new BrowserWindow({
        width: 1200,
        height: 800,
        webPreferences: {
            preload: path.resolve(__dirname, 'preload.js'),
        },
    });

    // リンクをふんだらブラウザに飛ばす処理
    const urlOpenhandler = (event: Electron.Event, url: string) => {
        if (url.match(/^http/)) {
            // Electronデフォルトの処理を停止
            event.preventDefault();
            // 既定のブラウザでurlを開く
            shell.openExternal(url);
        }
    };
    
    // リンクをクリックしたときの処理
    mainWindow.webContents.on('will-navigate', urlOpenhandler);
    // 新しいウィンドウを開こうとしたときの処理
    mainWindow.webContents.on('new-window', urlOpenhandler);
    // ここまで

    mainWindow.loadFile(path.resolve(__dirname, 'index.html'));
};

タスクトレイ登録

タスクトレイ登録というのは、Windowsでいう以下の画像に表示されているような場所にアイコンを表示させることです。

image (23).png

以下のサンプルコードを見れば使い方はなんとなくわかると思いますが、ドキュメントに色んな設定メニュー・オプションがのっているのでタスクトレイに他の機能を付けた場合は参照してください。

main.js
// グローバルスコープで定義
let tray = null;

app.on("ready", () => {
  createMainWindow();
 
 // タスクトレイ用のアイコンのパス定義
  const iconPath = path.resolve(
    __dirname,
    `iconName.${process.platform === "win32" ? "ico" : "png"}`
  );
 
 // trayのインスタンス化
  tray = new Tray(iconPath);
  // メニューの設定
  tray.setContextMenu(
    Menu.buildFromTemplate([
      {
        label: "リロード",
        click: () => {
          mainWindow.reload();
        },
      },
      {
        type: "separator",
      },
      {
        label: "Exit",
        role: "quit",
      },
    ])
  );
});

Windowsでは .ico ・Macでは.png 形式のアイコン画像を登録する必要があります。

trayをグローバルスコープではなくローカルスコープ(readyの中など)で定義してしまうと、本番環境ではガベージコレクションによってタスクトレイから消されてしまうことがあるので注意が必要です。

グローバルショートカット登録

Electoronではアプリにフォーカスが当たっていない状態でもショートカットを登録することができます。

globalShortcut.register(登録したいキー, () => 実行したいコード)というメゾットで簡単に設定することが可能です。ドキュメント

既にグローバルショートカットキーとして使用されているキーを登録はできません。
アプリを閉じる際はグローバルショートカットキーを解除してあげることが良心的だと思います。

以下、AltSpaceキーでアプリを出したり消したりするサンプルです。

main.js
app.on("ready", () => {
    globalShortcut.register("Alt+Space", () => {
    // アプリのウィンドウがユーザーに見えているかチェック
    if (mainWindow.isVisible()) {
      mainWindow.hide();
    } else {
      mainWindow.show();
      mainWindow.focus();
    }
  });

  createMainWindow();
});

app.on('will-quit', () => {
  // ショートカットの登録解除
  globalShortcut.unregister('Alt+Space')
})

Ctrl+S などをグローバルショートカットキーとして登録してしまうと、すべてのアプリにおいてCtrl+S 保存できないみたいなことが起こりえるのであまり使わないキーで登録しましょう。

フォーカスはずれたときに閉じたい

ランチャーアプリのようなアプリを作る際は、アプリからフォーカスが外れるとアプリを閉じたり隠したりしたいという場面が発生すると思います。

browser-window-blurを使えば、アプリのウィンドウからフォーカスが外れたときにイベントを起こすことができます。(ドキュメント)

main.js
app.on('ready', () => {
    createMainWindow();
});

app.on("browser-window-blur", () => {
  mainWindow.hide();
});

最後に

以上、僕がElectronでの開発時に使用したTipsでした!
どなたかの参考になれば幸いです。ありがとうございました:blush:

18
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?