T-CREATOR

Electron 入門 2025:Web 技術でデスクトップアプリを作る全体像

Electron 入門 2025:Web 技術でデスクトップアプリを作る全体像

Web 技術でデスクトップアプリケーションを開発できる Electron は、2025 年現在、多くの企業や開発者に愛用されている革新的なフレームワークです。Visual Studio Code、Discord、Slack、WhatsApp Desktop など、日常的に使用しているアプリケーションの多くが Electron で構築されています。

このガイドでは、Web 開発の知識を活かしてデスクトップアプリ開発に挑戦したい方に向けて、Electron の全体像を分かりやすく解説いたします。技術的な仕組みから実際の開発手順まで、段階的に学んでいきましょう。

背景

Web とデスクトップアプリの課題

従来、デスクトップアプリケーション開発には大きな課題がありました。Windows 向けには C#や C++、Mac 向けには Swift や Objective-C、Linux 向けには C++や Java といった、プラットフォーム固有の言語とフレームワークを習得する必要があったのです。

この状況は開発者にとって大きな負担でした。一つのアプリケーションを作るために、複数の言語を学び、それぞれ異なる開発環境を構築し、プラットフォームごとに別々のコードベースを維持する必要があります。

一方、Web 技術は急速に進歩し、HTML、CSS、JavaScript を使って豊富なユーザーインターフェースと複雑な機能を実現できるようになりました。しかし、これらの Web 技術で作成したアプリケーションは、ブラウザの中でしか動作せず、ファイルシステムへの直接アクセスや OS 固有の機能を利用することができませんでした。

Electron が解決する問題

Electron は、この二つの世界を橋渡しする画期的な解決策として登場しました。Web 技術(HTML、CSS、JavaScript)を使用してデスクトップアプリケーションを開発できるオープンソースフレームワークです。

以下の図は、Electron がどのように従来の課題を解決するかを示しています。

mermaidflowchart TD
    A[Web技術の習得] --> B[Electronアプリ開発]
    B --> C[Windows対応]
    B --> D[macOS対応]
    B --> E[Linux対応]
    F[一つのコードベース] --> B
    G[OS固有機能へのアクセス] --> B
    H[ファイルシステム操作] --> B

Electron の最大の利点は、一度のコード作成で複数のプラットフォーム(Windows、macOS、Linux)向けのアプリケーションを同時に開発できることです。Web 開発者が既に持っているスキルセットを活用して、デスクトップアプリケーション開発に参入できます。

2025 年の Electron 最新動向

2025 年現在、Electron は更なる進化を遂げています。セキュリティ機能の強化、パフォーマンスの向上、開発者体験の改善が継続的に行われており、企業レベルでの採用も増加しています。

主要な最新動向は以下の通りです。

項目2025 年の状況影響
セキュリティコンテキストアイソレーション標準化より安全なアプリ開発が可能
パフォーマンスメモリ使用量最適化軽量で高速なアプリ実現
開発体験TypeScript 完全サポート型安全な開発環境
自動更新新しい更新システムユーザー体験の向上

課題

従来の開発手法の限界

デスクトップアプリ開発の従来手法には、開発効率とコスト面で深刻な課題がありました。

最大の問題は、プラットフォームごとに異なる技術スタックが必要になることです。Windows 向けアプリを開発するためには C#や Visual Studio、Mac 向けには Swift や Xcode、Linux 向けには C++や Qt framework といった具合に、それぞれ専門的な知識と開発環境が必要でした。

この状況により、開発チームは以下のような困難に直面していました。

  • 学習コストの増大: 複数の言語とフレームワークの習得
  • 開発期間の延長: プラットフォームごとの個別実装
  • 保守コストの増加: 複数のコードベースの管理
  • 人材確保の困難: 各プラットフォームの専門家が必要

Web 技術でデスクトップアプリを作る際の障壁

Web 技術は確かに優れていますが、デスクトップアプリ開発に応用する際には技術的な障壁がありました。

ブラウザ環境で動作する Web アプリケーションは、セキュリティ上の理由から、ファイルシステムへの直接アクセスや、OS 固有の API を呼び出すことが制限されています。デスクトップアプリに求められる以下の機能を実現することができませんでした。

  • ローカルファイルの読み書き
  • システム通知の表示
  • メニューバーやタスクトレイの操作
  • キーボードショートカットの登録
  • 他のアプリケーションとの連携

パフォーマンスとメモリ消費の課題

Electron アプリケーションは、Chromium ブラウザエンジン上で動作するため、ネイティブアプリケーションと比較してメモリ使用量が多くなる傾向があります。

以下の比較表は、一般的なアプリケーションのメモリ使用量を示しています。

アプリタイプ平均メモリ使用量起動時間
ネイティブアプリ50-100MB1-2 秒
Electron アプリ100-200MB2-4 秒
ブラウザベースアプリ150-300MB3-6 秒

この課題に対して、開発者は以下の点を考慮する必要があります。

  • リソース効率の最適化
  • ユーザー体験への影響評価
  • ターゲットハードウェアの仕様確認

解決策

Electron アーキテクチャの仕組み

Electron は、Chromium と Node.js を組み合わせた独特のアーキテクチャを採用しています。この設計により、Web 技術でデスクトップアプリケーションを開発できる環境を実現しています。

Electron アプリケーションのアーキテクチャを図で説明いたします。

mermaidflowchart TB
    subgraph electron[Electronアプリケーション]
        main[メインプロセス<br/>Node.js環境]
        renderer1[レンダラープロセス<br/>Chromium環境]
        renderer2[レンダラープロセス<br/>Chromium環境]
    end

    main -->|IPC通信| renderer1
    main -->|IPC通信| renderer2
    main -->|API呼び出し| os[OS固有機能]
    renderer1 -->|Web技術| ui1[UI表示]
    renderer2 -->|Web技術| ui2[UI表示]

このアーキテクチャにより、Web 技術の利点を活かしながら、デスクトップアプリケーションに必要な機能を実現できます。

メインプロセスとレンダラープロセス

Electron アプリケーションは、主に二つのタイプのプロセスで構成されています。

メインプロセスは、アプリケーション全体を管理する中心的な役割を担います。Node.js 環境で動作し、以下の責任があります。

  • アプリケーションのライフサイクル管理
  • ウィンドウの作成と管理
  • OS 固有の API へのアクセス
  • ファイルシステム操作
  • レンダラープロセスとの通信

メインプロセスの基本的な実装例を見てみましょう。

javascriptconst { app, BrowserWindow } = require('electron');
const path = require('path');

// メインプロセスの作成
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  mainWindow.loadFile('index.html');
}

レンダラープロセスは、ユーザーインターフェースを表示する役割を担います。Chromium 環境で動作し、HTML、CSS、JavaScript を使って UI を構築します。

各ウィンドウが独立したレンダラープロセスとして動作するため、一つのウィンドウでエラーが発生しても、他のウィンドウには影響しません。

html<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Electronアプリ</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <h1>Hello Electron!</h1>
    <button id="fileBtn">ファイルを開く</button>
    <script src="renderer.js"></script>
  </body>
</html>

IPC による通信方法

メインプロセスとレンダラープロセス間の通信は、IPC(Inter-Process Communication)を使用して行われます。セキュリティを保ちながら、プロセス間でデータをやり取りできます。

以下は、IPC を使った通信の実装例です。

preload.js(セキュアな通信の橋渡し)

javascriptconst { contextBridge, ipcRenderer } = require('electron');

// レンダラープロセスに安全なAPIを提供
contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('dialog:openFile'),
  saveFile: (content) =>
    ipcRenderer.invoke('dialog:saveFile', content),
  onMenuClick: (callback) =>
    ipcRenderer.on('menu:click', callback),
});

メインプロセス側の実装

javascriptconst { ipcMain, dialog } = require('electron');

// ファイルダイアログの処理
ipcMain.handle('dialog:openFile', async () => {
  const result = await dialog.showOpenDialog({
    properties: ['openFile'],
    filters: [
      { name: 'テキストファイル', extensions: ['txt'] },
      { name: 'すべてのファイル', extensions: ['*'] },
    ],
  });

  if (!result.canceled) {
    return result.filePaths[0];
  }
});

レンダラープロセス側の実装

javascript// ボタンクリック時のファイル選択
document
  .getElementById('fileBtn')
  .addEventListener('click', async () => {
    const filePath = await window.electronAPI.openFile();
    if (filePath) {
      console.log('選択されたファイル:', filePath);
    }
  });

セキュリティ対策

Electron アプリケーションのセキュリティは非常に重要です。2025 年現在、セキュリティベストプラクティスが確立されており、これらを適切に実装することで安全なアプリケーションを開発できます。

主要なセキュリティ対策は以下の通りです。

対策項目実装方法効果
コンテキストアイソレーションcontextIsolation: trueレンダラーから Node.js への直接アクセス防止
Node.js 統合無効化nodeIntegration: falseWeb 環境のセキュリティ維持
セキュアな preloadpreload スクリプトの使用安全な API 提供
CSP ヘッダーContent Security PolicyXSS 攻撃の防止

具体例

Hello World アプリの作成

実際に Electron アプリケーションを作成してみましょう。最初は最もシンプルな Hello World アプリから始めます。

プロジェクトの初期化

まず、新しいプロジェクトディレクトリを作成し、必要なパッケージをインストールします。

bashmkdir my-electron-app
cd my-electron-app
yarn init -y
yarn add --dev electron

package.json の設定

json{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "My first Electron app",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "dev": "electron . --development"
  },
  "devDependencies": {
    "electron": "^latest"
  }
}

メインプロセスの作成(main.js)

javascriptconst { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow() {
  // ブラウザウィンドウを作成
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  // HTMLファイルをロード
  mainWindow.loadFile('index.html');

  // 開発時にはDevToolsを開く
  if (process.argv.includes('--development')) {
    mainWindow.webContents.openDevTools();
  }
}

// アプリの準備が完了したらウィンドウを作成
app.whenReady().then(createWindow);

// 全てのウィンドウが閉じられたらアプリを終了(macOS以外)
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

// アプリがアクティブになったらウィンドウを作成(macOS)
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

HTML ファイルの作成(index.html)

html<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello Electron</title>
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self' 'unsafe-inline';"
    />
    <style>
      body {
        font-family: Arial, sans-serif;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        margin: 0;
        background: linear-gradient(
          135deg,
          #667eea 0%,
          #764ba2 100%
        );
        color: white;
      }

      .container {
        text-align: center;
        padding: 2rem;
        border-radius: 10px;
        background: rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>Hello Electron!</h1>
      <p>Web技術でデスクトップアプリを作成できました</p>
      <button id="greetBtn">挨拶する</button>
      <p id="greeting"></p>
    </div>
    <script src="renderer.js"></script>
  </body>
</html>

preload スクリプト(preload.js)

javascriptconst { contextBridge } = require('electron');

// レンダラープロセスに安全なAPIを提供
contextBridge.exposeInMainWorld('electronAPI', {
  getGreeting: () => {
    const greetings = [
      'こんにちは!Electronの世界へようこそ!',
      'Web技術でデスクトップアプリが作れるなんて素晴らしいですね!',
      'あなたのElectron開発の旅が始まりました!',
    ];
    return greetings[
      Math.floor(Math.random() * greetings.length)
    ];
  },
});

レンダラープロセス(renderer.js)

javascript// DOMの読み込み完了を待つ
document.addEventListener('DOMContentLoaded', () => {
  const greetBtn = document.getElementById('greetBtn');
  const greeting = document.getElementById('greeting');

  greetBtn.addEventListener('click', () => {
    const message = window.electronAPI.getGreeting();
    greeting.textContent = message;

    // ボタンにアニメーション効果を追加
    greetBtn.style.transform = 'scale(0.95)';
    setTimeout(() => {
      greetBtn.style.transform = 'scale(1)';
    }, 100);
  });
});

アプリケーションの実行

bashyarn start

これで、最初の Electron アプリケーションが完成しました。

ファイル操作アプリの実装

次に、より実用的なファイル操作機能を持つアプリケーションを作成してみましょう。このアプリでは、テキストファイルの読み込み、編集、保存ができます。

メインプロセスにファイル操作機能を追加

javascriptconst { ipcMain, dialog } = require('electron');
const fs = require('fs').promises;

// ファイルオープンダイアログ
ipcMain.handle('dialog:openFile', async () => {
  const result = await dialog.showOpenDialog({
    properties: ['openFile'],
    filters: [
      {
        name: 'テキストファイル',
        extensions: ['txt', 'md', 'js', 'html', 'css'],
      },
      { name: 'すべてのファイル', extensions: ['*'] },
    ],
  });

  if (!result.canceled && result.filePaths.length > 0) {
    try {
      const filePath = result.filePaths[0];
      const content = await fs.readFile(filePath, 'utf8');
      return { filePath, content };
    } catch (error) {
      throw new Error(
        `ファイル読み込みエラー: ${error.message}`
      );
    }
  }
  return null;
});

// ファイル保存ダイアログ
ipcMain.handle(
  'dialog:saveFile',
  async (event, content) => {
    const result = await dialog.showSaveDialog({
      filters: [
        { name: 'テキストファイル', extensions: ['txt'] },
        { name: 'すべてのファイル', extensions: ['*'] },
      ],
    });

    if (!result.canceled) {
      try {
        await fs.writeFile(
          result.filePath,
          content,
          'utf8'
        );
        return result.filePath;
      } catch (error) {
        throw new Error(
          `ファイル保存エラー: ${error.message}`
        );
      }
    }
    return null;
  }
);

UI の拡張

html<div class="container">
  <div class="toolbar">
    <button id="openBtn">ファイルを開く</button>
    <button id="saveBtn">ファイルを保存</button>
    <button id="newBtn">新規作成</button>
  </div>

  <div class="editor-container">
    <div class="file-info">
      <span id="fileName">新規ファイル</span>
      <span id="fileStatus"></span>
    </div>
    <textarea
      id="editor"
      placeholder="ここにテキストを入力してください..."
    ></textarea>
  </div>

  <div class="status-bar">
    <span id="charCount">0文字</span>
    <span id="lineCount">1行</span>
  </div>
</div>

ネイティブ API との連携

Electron では、OS 固有の機能にアクセスできます。通知機能を例に実装してみましょう。

通知機能の実装

javascript// メインプロセス側
const { Notification } = require('electron');

ipcMain.handle(
  'notification:show',
  async (event, title, body) => {
    if (Notification.isSupported()) {
      new Notification({
        title: title,
        body: body,
        icon: path.join(__dirname, 'assets', 'icon.png'),
      }).show();
      return true;
    }
    return false;
  }
);

// システムトレイの実装
const { Tray, Menu } = require('electron');

let tray = null;

function createTray() {
  tray = new Tray(
    path.join(__dirname, 'assets', 'tray-icon.png')
  );

  const contextMenu = Menu.buildFromTemplate([
    {
      label: 'アプリを表示',
      click: () => mainWindow.show(),
    },
    { label: '終了', click: () => app.quit() },
  ]);

  tray.setToolTip('My Electron App');
  tray.setContextMenu(contextMenu);
}

パッケージ化とビルド

開発が完了したら、アプリケーションを配布可能な形式にパッケージ化します。

electron-builder の設定

bashyarn add --dev electron-builder

package.json にビルド設定を追加

json{
  "build": {
    "appId": "com.example.myapp",
    "productName": "My Electron App",
    "directories": {
      "output": "dist"
    },
    "files": [
      "**/*",
      "!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}",
      "!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples}",
      "!**/node_modules/*.d.ts",
      "!**/node_modules/.bin",
      "!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}",
      "!.editorconfig",
      "!**/._*",
      "!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}",
      "!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}",
      "!**/{appveyor.yml,.travis.yml,circle.yml}",
      "!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json}"
    ],
    "mac": {
      "category": "public.app-category.productivity"
    },
    "win": {
      "target": "nsis"
    },
    "linux": {
      "target": "AppImage"
    }
  },
  "scripts": {
    "build": "electron-builder",
    "build:win": "electron-builder --win",
    "build:mac": "electron-builder --mac",
    "build:linux": "electron-builder --linux"
  }
}

ビルドの実行

bash# 全プラットフォーム向けビルド
yarn build

# Windows向けのみ
yarn build:win

# macOS向けのみ
yarn build:mac

# Linux向けのみ
yarn build:linux

このパッケージ化により、ユーザーは簡単にアプリケーションをインストールできるようになります。

まとめ

Electron の利点と注意点

Electron を使用したデスクトップアプリ開発には、多くの利点と考慮すべき注意点があります。

主な利点

  • クロスプラットフォーム対応: 一つのコードベースで複数の OS に対応
  • 学習コストの低減: 既存の Web 開発スキルを活用可能
  • 開発効率の向上: 迅速なプロトタイピングと開発が可能
  • 豊富なエコシステム: npm の膨大なライブラリを活用可能
  • UI/UX の自由度: Web 技術によるリッチなインターフェース設計

注意すべき点

  • メモリ使用量: ネイティブアプリより多くのメモリを消費
  • アプリサイズ: Chromium を含むため、アプリサイズが大きくなる
  • パフォーマンス: 高負荷処理では最適化が必要
  • セキュリティ: 適切なセキュリティ対策の実装が重要

これらの特性を理解した上で、プロジェクトの要件に応じて技術選択を行うことが大切です。

開発効率の向上効果

実際のプロジェクトで Electron を採用した場合の開発効率向上効果を見てみましょう。

開発フェーズ従来手法Electron 手法効率化率
環境構築3-5 日1 日70%向上
プロトタイプ作成2-3 週間3-5 日80%向上
クロスプラットフォーム対応4-6 週間1 週間85%向上
UI/UX 実装3-4 週間1-2 週間60%向上
テスト・デバッグ2-3 週間1 週間65%向上

特に、スタートアップや中小企業において、限られたリソースで多機能なデスクトップアプリケーションを開発する際に、Electron の恩恵は非常に大きくなります。

今後の展望

2025 年以降、Electron は以下の方向で更なる進化が期待されています。

技術的な進歩

  • パフォーマンス最適化: WebAssembly との統合によるさらなる高速化
  • メモリ効率の改善: より軽量なランタイムの提供
  • セキュリティ強化: ゼロトラストアーキテクチャの採用
  • 開発者体験: より直感的なデバッグツールとプロファイリング機能

エコシステムの拡大

  • フレームワーク統合: React、Vue、Angular との更なる連携強化
  • クラウド連携: クラウドサービスとの密接な統合
  • AI 機能: 機械学習ライブラリとの統合サポート

これらの進歩により、Electron は今後も Web 技術とデスクトップアプリ開発の橋渡し役として重要な位置を占め続けるでしょう。Web 開発者にとって、Electron のスキル習得は将来的な技術投資として非常に価値のあるものとなっています。

関連リンク