PL
Electron
Programming Lab / Desktop App with Web Tech

Electron

Electron は ChromiumNode.js を同梱し、JavaScript / HTML / CSS で Windows / macOS / Linux 向けデスクトップアプリを作るフレームワーク。:contentReference[oaicite:3]{index=3}

Electron Logo
Electron
得意
Web UI × OS機能
注意
実行サイズが大きい
代替
Tauri / Wails

概要

  • Web技術でデスクトップアプリを作る(UIはHTML/CSS、ロジックはJS)。:contentReference[oaicite:4]{index=4}
  • Chromium(描画)+ Node.js(OSアクセス)を同梱して“ネイティブっぽく”動かす。:contentReference[oaicite:5]{index=5}
  • Electronチームは「最新3つの安定メジャー」をサポート方針として明示。:contentReference[oaicite:6]{index=6}
Elektron どこの国?
Elektron(k)は Electron とは別で、スウェーデンの電子楽器メーカー(ヨーテボリ本社)。:contentReference[oaicite:7]{index=7}

Electronとは何ですか?どういうフレームワーク?

Electron は、JavaScript / HTML / CSS でデスクトップアプリを構築するためのフレームワークです。 ChromiumNode.js をバイナリに組み込むことで、単一コードベースで Windows / macOS / Linux を狙えます。:contentReference[oaicite:8]{index=8}

向いてる

  • Webエンジニアが素早くデスクトップへ
  • UIをWebで作り込みたい
  • クロスプラットフォームが最優先

悩みどころ

  • アプリサイズが重くなりやすい
  • セキュリティ設計(特にIPC)が重要

Electronで作られたアプリは?

公式サイトの「Apps users love」には、例として 1Password / Asana / Claude / Discord / Dropbox / Figma / Loom / GitHub Desktop などが掲載されています。:contentReference[oaicite:9]{index=9} また GitHub のElectronリポジトリ説明でも Visual Studio Code などで使われている旨が示されています。:contentReference[oaicite:10]{index=10}

Visual Studio Code Discord Figma GitHub Desktop 1Password Asana Dropbox Loom Claude

仕組み・アーキテクチャ

Main Process
アプリのライフサイクル管理 / BrowserWindow作成 / OS連携 / IPCハブ
IPC (安全設計が超重要)
Renderer Process
画面(HTML/CSS)描画。必要な機能は preload 経由で限定公開。
基本の安全方針
renderer に Node.js を直結させず、preload + contextIsolation で「必要最小限のAPIだけ」渡すのが王道です(後述)。

Electron を始める(最短)

1) Node.js を入れる

Node.js が必要です(npm を使います)。

2) プロジェクト作成

mkdir my-electron-app
cd my-electron-app
npm init -y
npm i -D electron

3) 起動スクリプト

{
  "name": "my-electron-app",
  "version": "0.1.0",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  }
}

最小テンプレ(雛形)

main.js

const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");

function createWindow(){
  const win = new BrowserWindow({
    width: 1100,
    height: 720,
    backgroundColor: "#0b1220",
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true,
    }
  });

  win.loadFile("index.html");
}

app.whenReady().then(() => {
  createWindow();

  // macOS での一般的な挙動
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

// 全ウィンドウ閉じたら終了(macOSは例外が多いので好みで調整)
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});

// 例:安全に限定したIPC
ipcMain.handle("app:ping", async () => {
  return { ok: true, time: new Date().toISOString() };
});

preload.js

const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("api", {
  ping: () => ipcRenderer.invoke("app:ping"),
});

index.html

<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>My Electron App</title>
  <style>
    body{font-family:system-ui, "Noto Sans JP"; margin:0; padding:24px; color:#e5e7eb; background:#0b1220;}
    .card{max-width:820px; border:1px solid rgba(148,163,184,.22); border-radius:16px; padding:18px; background:rgba(255,255,255,.06);}
    button{padding:10px 12px; border-radius:12px; border:1px solid rgba(148,163,184,.25); background:rgba(255,255,255,.08); color:#e5e7eb; cursor:pointer;}
  </style>
</head>
<body>
  <div class="card">
    <h1>Hello Electron</h1>
    <p>renderer から preload 経由で main と通信します。</p>
    <button id="btn">Ping</button>
    <pre id="out"></pre>
  </div>

  <script>
    const btn = document.getElementById("btn");
    const out = document.getElementById("out");
    btn.addEventListener("click", async () => {
      const res = await window.api.ping();
      out.textContent = JSON.stringify(res, null, 2);
    });
  </script>
</body>
</html>

セキュリティ要点

  • nodeIntegration: false(rendererから Node を直で触らせない)
  • contextIsolation: true(window汚染を避ける)
  • preload で API を絞る(必要最小限の橋渡し)
  • 外部URLをそのまま loadURL しない(するなら強い制限が必要)

配布・ビルド

配布は electron-builderelectron-forge が定番です(どちらも選べます)。

# 例:electron-builder を入れる
npm i -D electron-builder

# package.json に build 設定を書いて
# npm run dist で各OS向けにパッケージ化
バージョン追従の考え方
Electron は「最新3つの安定メジャーをサポート」方針。Chromium/Node同梱なので、 セキュリティ面でも追従を前提に運用設計するとラクです。:contentReference[oaicite:11]{index=11}

Tauri / Wails など代替

「サイズを軽くしたい」「OSのWebViewを活用したい」などの動機で、 Rust/Go バックエンドの Tauri / Wails が候補になります(思想としては“同じ目的の別解”)。

Electron

  • Chromium同梱で表現力が強い
  • エコシステムが巨大
  • サイズが重くなりやすい

Tauri / Wails

  • 軽量化を狙いやすい
  • Rust/Go を活かせる
  • UI差分(WebView依存)に注意