⚡️

Electronを使ってデスクトップアプリを作る

2024/12/28に公開

Mac book Pro M1 チップ
MacOs Sonoma ver14.2.1


Electron とは

Electron は、JavaScript、HTML、CSS などの Web 技術を使ってデスクトップアプリケーションを開発できるオープンソースのフレームワークです。Chromium と Node.js を基盤とし、クロスプラットフォーム対応(Windows、macOS、Linux)のアプリを一度の開発で提供可能です。

準備 ー Node.js の導入

Electron でアプリを開発するには、Node.js をインストールする必要があります。
Node.js は JavaScript を用いてサーバーサイド機能を実現するランタイムであり、Electron に組み込まれることで、デスクトップアプリからファイルシステムやプロセス管理、ネットワーク通信などのネイティブ機能にアクセス可能となります。これにより、JavaScript だけでフロントエンドとバックエンドの両方を開発でき、効率的な開発環境を提供します。

実際の開発環境では、複数の Node.js バージョンを取り扱うこともあるので、Node.js バージョン管理システムの nvm を使用します。
nvm 公式サイト

nvm をインストールします

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

~/.zshrc に自動で追記されたようなので確認します。

[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion```

OK ならターミナル再起動か、source ~/.zshrc 実行でインストール完了

nvm -v
==> 0.40.1

Node.js 公式サイト:https://nodejs.org/en/download/package-manager
nvm で Node.js をインストールする

nvm install 22
node -v
==> v22.12.0
npm -v
==> 10.9.0

アプリケーションの作成

ワークディレクトリを作って Node.js のプロジェクトとして初期化します。

cd <work_dir>
npm init --yes

package.json が作られるので、下記のように編集する。
この時、エンドポイントは必ず「main.jp」であること。
また、author と description はどのような値でも構いませんが、アプリのパッケージ化 で必要になる。

package.json
{
  "name": "Sample-app",
  "version": "1.0.0",
  "description": "Hello World!",
  "main": "main.js",
  "author": "Your name",
  "license": "MIT"
}

electron をインストールする

npm install --save-dev electron

package.json に electron が追加された

package.json
+ "devDependencies": {
+    "electron": "^33.2.1"
+  }

package.json を編集して、Elrctron を実行する npm スクリプトを設定する。

package.json
{
  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1",
+   "start": "electron ."
  },
}

Electron クイックスタート を参考に、node バージョン、Chromium バージョン、Electron バージョンを表示するアプリを作成します。
index.html, main.js, preload.js の3つのファイルを用意します。
ディレクトリ構成はこんな感じ。

 tree -a -L 1
.
├── index.html
├── main.js
├── node_modules
├── package-lock.json
├── package.json
└── preload.js
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>, Chromium
    <span id="chrome-version"></span>, and Electron
    <span id="electron-version"></span>.
  </body>
</html>
main.js
// このモジュールはアプリケーションの生き死にを制御し、ネイティブブラウザウインドウを作成します
const { app, BrowserWindow } = require("electron");
const path = require("node:path");

const createWindow = () => {
  // ブラウザウインドウを作成します。
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    //
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
    },
  });

  // index.html を新規作成した BrowserWindow インスタンスに読み込ませる
  mainWindow.loadFile("index.html");

  // デベロッパー ツールを開きます。
  mainWindow.webContents.openDevTools();
};

// Electron の初期化が完了し、ラウザウインドウの作成準備ができたときに呼ばれる。
// 一部のAPIはこのイベントが発生した後にのみ利用できる。
app.whenReady().then(() => {
  createWindow();

  app.on("activate", () => {
    // 開いたウインドウがない場合にウインドウを開く (macOS)
    // activateイベントは、macOSでアプリケーションがアクティブになったときに発生します。
    // 例えば、Dockアイコンをクリックしたときなどです。
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// 全ウインドウを閉じた時にアプリを終了する (Windows & Linux)
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});
preload.js
// Electronのプリロードスクリプト(preload.js)は、レンダラープロセス(ウェブページ)と
// メインプロセス(Node.js環境)間のブリッジとして機能します。プ
// リロードスクリプトは、ウェブページが読み込まれる前に実行され、
// Node.jsのAPIを安全に使用できるようにします。
window.addEventListener("DOMContentLoaded", () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector);
    if (element) element.innerText = text;
  };

  for (const dependency of ["chrome", "node", "electron"]) {
    replaceText(`${dependency}-version`, process.versions[dependency]);
  }
});

それでは実行してみます。

npm start

sampleApp
アプリが起動しました。
Nodo.js のバージョンが表示されていますが、インストールしたバージョンと異なっています。
これは、process.versions.node が Electron のバージョンを返しているためです。
Electron は Node.js を内部で使用していますが、Electron 自体のバージョンに依存する Node.js のバージョンを使用します。そのため、インストールした Node.js のバージョンとは異なる場合があります。

Electron Forge でアプリをパッケージ化する

今のコードではデベロッパーツールが表示されたままなので、コメントアウトしておきます。

main.js
const createWindow = () => {
  // ブラウザウインドウを作成します。
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    //
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
    },
  });

  // index.html を新規作成した BrowserWindow インスタンスに読み込ませる
  mainWindow.loadFile("index.html");

  // デベロッパー ツールを開きます。
-   mainWindow.webContents.openDevTools();
+ // mainWindow.webContents.openDevTools();
};

Electron Forge CLI を開発依存としてインストールします

npm install --save-dev @electron-forge/cli

既存の Electron プロジェクトを Electron Forge プロジェクトに変換します

npx electron-forge import

Electron アプリケーションのソースコードがビルドします。

npm run make

生成されたパッケージは、out ディレクトリに保存されます。
Mac 用のアプリケーションファイルが作成されました。
package
※ Mac 環境で Windows 用パッケージを作成するのは一筋縄では行きそうにないので、それはまた今度。

Discussion