記事一覧に戻る

はじめてのElectronアプリ - Hello Worldから始める開発

9分で読めます
ElectronチュートリアルHello World

はじめてのElectronアプリ - Hello Worldから始める開発

はじめに

プログラミングの学習において、「Hello World」は最初の一歩として長い歴史を持つ伝統的なプログラムです。新しい技術を学ぶ際に、まずは最小限の動作するプログラムを作ることで、その技術の基本的な構造や動作原理を理解できます。

本記事では、Electronを使った最初のデスクトップアプリケーションを作成する過程を、環境構築から実際の実装、そして実行まで丁寧に解説します。プログラミング初心者の方でも迷わないよう、各ステップを詳しく説明していきますので、安心して進めてください。

開発環境の準備

必要なツールのインストール

Electronアプリケーションを開発するには、まず以下のツールをインストールする必要があります。

Node.js

Node.jsは、JavaScriptをブラウザの外で実行するためのランタイム環境です。Electronの実行に必要不可欠なツールです。

インストール手順:

  1. Node.js公式サイト(nodejs.org)にアクセス
  2. LTS(Long Term Support)版をダウンロード(安定性を重視)
  3. ダウンロードしたインストーラーを実行
  4. インストールウィザードに従って進める

インストールが完了したら、コマンドライン(Windows: コマンドプロンプト、Mac/Linux: ターミナル)で以下のコマンドを実行して、正しくインストールされたことを確認します:

bash
node --version
npm --version

これらのコマンドでバージョン番号が表示されれば、インストールは成功です。Node.jsをインストールすると、npm(Node Package Manager)も同時にインストールされます。npmは、JavaScriptのパッケージを管理するツールで、Electronのインストールにも使用します。

コードエディタ

コードを書くためのエディタも必要です。Visual Studio Code(VS Code)を推奨します。VS Code自体もElectronで作られており、Electron開発に最適な機能が豊富に用意されています。

VS Codeの主な利点:

  • 無料で利用可能
  • 日本語化が可能
  • Electron開発に便利な拡張機能が豊富
  • 統合ターミナル機能
  • インテリセンス(コード補完)機能

プロジェクトディレクトリの作成

開発を始める前に、プロジェクト用のディレクトリ(フォルダ)を作成します。

bash
# プロジェクトディレクトリを作成
mkdir my-electron-app

# 作成したディレクトリに移動
cd my-electron-app

ディレクトリ名は自由に決められますが、わかりやすい名前を付けることをおすすめします。スペースや日本語は避け、半角英数字とハイフン、アンダースコアのみを使用するのが一般的です。

package.jsonの初期化

Node.jsプロジェクトでは、package.jsonというファイルでプロジェクトの設定や依存関係を管理します。以下のコマンドで初期化します:

bash
npm init -y

-yオプションを付けることで、デフォルト設定で自動的にpackage.jsonが作成されます。作成されたpackage.jsonの内容を確認してみましょう:

json
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

このファイルには、プロジェクトの基本情報が記載されています。後ほど、Electron用の設定を追加していきます。

Electronのインストールと基本設定

Electronパッケージのインストール

npmを使用してElectronをインストールします:

bash
npm install --save-dev electron

このコマンドの各部分の意味:

  • npm install: パッケージをインストールするコマンド
  • --save-dev: 開発時のみ必要な依存関係として記録
  • electron: インストールするパッケージ名

インストールには数分かかることがあります。完了すると、node_modulesディレクトリが作成され、その中にElectronと関連するパッケージがダウンロードされます。

package.jsonの設定更新

Electronアプリケーションとして動作させるため、package.jsonを以下のように更新します:

json
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "My first Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": ["electron", "desktop", "app"],
  "author": "Your Name",
  "license": "MIT",
  "devDependencies": {
    "electron": "^28.0.0"
  }
}

主な変更点:

  • main: エントリーポイントをmain.jsに変更
  • scripts.start: electron .コマンドを追加(アプリケーションの起動用)
  • description: アプリケーションの説明を追加
  • license: ライセンスをMITに変更(オープンソースの一般的なライセンス)

最初のElectronアプリケーションの作成

メインプロセスの実装

まず、メインプロセスのコードを作成します。プロジェクトのルートディレクトリにmain.jsというファイルを作成し、以下のコードを記述します:

javascript
// Electronモジュールをインポート
const { app, BrowserWindow } = require('electron')
const path = require('path')

// ウィンドウオブジェクトをグローバル参照として保持
let mainWindow

function createWindow() {
  // ブラウザウィンドウを作成
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // プリロードスクリプトのパスを指定
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // index.htmlを読み込む
  mainWindow.loadFile('index.html')

  // ウィンドウが閉じられた時の処理
  mainWindow.on('closed', () => {
    mainWindow = null
  })
}

// Electronの初期化が完了したらウィンドウを作成
app.whenReady().then(() => {
  createWindow()

  // macOSの場合、アプリケーションをアクティブ化した時の処理
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

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

このコードの各部分について詳しく説明します:

モジュールのインポート部分では、Electronから必要な機能をインポートしています。appはアプリケーション全体を制御するオブジェクト、BrowserWindowは新しいウィンドウを作成するためのクラスです。

createWindow関数は、アプリケーションのメインウィンドウを作成する関数です。BrowserWindowのコンストラクタに渡すオプションで、ウィンドウのサイズや動作を設定できます。

**app.whenReady()**は、Electronの初期化が完了した時に実行されるPromiseを返します。この時点で初めてウィンドウを作成できるようになります。

プラットフォーム固有の処理として、macOSでは全てのウィンドウを閉じてもアプリケーションは終了せず、Dockに残る仕様があります。そのため、process.platformでOSを判定し、適切な処理を行っています。

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

次に、実際に表示されるHTMLファイルを作成します。index.htmlというファイルを作成し、以下の内容を記述します:

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- CSPの設定でセキュリティを強化 -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        .container {
            max-width: 600px;
            margin: 0 auto;
            background-color: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
            text-align: center;
        }
        .info {
            background-color: #e3f2fd;
            padding: 15px;
            border-radius: 5px;
            margin-top: 20px;
        }
        .version-info {
            font-family: monospace;
            color: #666;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Hello World!</h1>
        <p>初めてのElectronアプリケーションへようこそ!</p>
        
        <div class="info">
            <h2>バージョン情報</h2>
            <p class="version-info">
                Node.js: <span id="node-version"></span><br>
                Chromium: <span id="chrome-version"></span><br>
                Electron: <span id="electron-version"></span>
            </p>
        </div>
        
        <div class="info">
            <h2>このアプリケーションについて</h2>
            <p>
                このアプリケーションはElectronで作成されています。
                Web技術(HTML、CSS、JavaScript)を使用して、
                クロスプラットフォームなデスクトップアプリケーションを
                開発できます。
            </p>
        </div>
    </div>
    
    <!-- レンダラープロセスのスクリプトを読み込む -->
    <script src="renderer.js"></script>
</body>
</html>

このHTMLファイルは、通常のWebページと同じ構造を持っていますが、いくつかElectron特有の要素があります。特に重要なのは、Content Security Policy(CSP)の設定です。これにより、外部スクリプトの実行を防ぎ、セキュリティを向上させています。

プリロードスクリプトの作成

セキュリティを確保しながら、レンダラープロセスに必要な機能を提供するため、プリロードスクリプトを作成します。preload.jsというファイルを作成し、以下の内容を記述します:

javascript
// プリロードスクリプト
// レンダラープロセスがロードされる前に実行される

// バージョン情報をwindowオブジェクトに追加
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])
  }
})

プリロードスクリプトは、レンダラープロセスのWebページが読み込まれる前に実行される特別なスクリプトです。Node.js APIにアクセスできる一方で、Webページのグローバルスコープとは分離されているため、セキュアな方法でNode.jsの機能を使用できます。

このスクリプトでは、DOMContentLoadedイベントを待ってから、各コンポーネント(Chrome、Node.js、Electron)のバージョン情報をHTMLに挿入しています。

レンダラースクリプトの作成

最後に、レンダラープロセスで実行されるJavaScriptファイルを作成します。renderer.jsというファイルを作成し、以下の内容を記述します:

javascript
// レンダラープロセスのスクリプト
// 通常のWebページのJavaScriptと同じように動作する

// ページ読み込み完了後の処理
document.addEventListener('DOMContentLoaded', () => {
  console.log('レンダラープロセスが起動しました')
  
  // 現在時刻を表示する要素を追加
  const timeElement = document.createElement('div')
  timeElement.className = 'info'
  timeElement.innerHTML = '<h2>現在時刻</h2><p id="current-time"></p>'
  document.querySelector('.container').appendChild(timeElement)
  
  // 1秒ごとに時刻を更新
  function updateTime() {
    const now = new Date()
    const timeString = now.toLocaleString('ja-JP')
    document.getElementById('current-time').textContent = timeString
  }
  
  updateTime()
  setInterval(updateTime, 1000)
})

このスクリプトは、通常のWebページのJavaScriptと同じように動作します。DOMの操作、イベントの処理、タイマーの使用など、ブラウザで利用できる機能をすべて使用できます。

アプリケーションの実行

初回起動

すべてのファイルが準備できたら、いよいよアプリケーションを起動します。ターミナルで以下のコマンドを実行します:

bash
npm start

このコマンドは、package.jsonのscripts.startに定義したelectron .を実行します。正常に起動すると、新しいウィンドウが開き、作成したHTMLページが表示されます。

初回起動時によくある問題と解決方法:

ウィンドウが表示されない場合

  • ファイル名が正しいか確認(main.js、index.html)
  • package.jsonのmainフィールドが正しく設定されているか確認
  • コンソールにエラーメッセージが表示されていないか確認

白い画面が表示される場合

  • index.htmlのパスが正しいか確認
  • HTMLファイルの構文エラーがないか確認
  • 開発者ツールでコンソールエラーを確認

開発者ツールの使い方

Electronアプリケーションでは、ChromeのDevToolsを使用してデバッグできます。開発者ツールを開くには、以下の方法があります:

  1. メニューから開く:View → Toggle Developer Tools
  2. キーボードショートカット
    • Windows/Linux: Ctrl + Shift + I
    • macOS: Cmd + Option + I
  3. プログラムから開く:main.jsに以下のコードを追加
javascript
// main.jsのcreateWindow関数内に追加
mainWindow.webContents.openDevTools()

開発者ツールでは、以下の機能が利用できます:

  • Console: JavaScriptのエラーやconsole.logの出力を確認
  • Elements: HTMLの構造とCSSを確認・編集
  • Sources: JavaScriptのデバッグ(ブレークポイントの設定)
  • Network: ネットワークリクエストの監視
  • Performance: パフォーマンスの分析

機能の追加と拡張

ボタンによるインタラクション

アプリケーションをより対話的にするため、ボタンを追加してみましょう。index.htmlに以下のコードを追加します:

html
<!-- index.htmlの.containerクラス内に追加 -->
<div class="info">
    <h2>インタラクション</h2>
    <button id="hello-btn" style="
        padding: 10px 20px;
        font-size: 16px;
        background-color: #2196F3;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    ">クリックしてください</button>
    <p id="message" style="margin-top: 10px;"></p>
</div>

そして、renderer.jsに以下のコードを追加します:

javascript
// ボタンクリックイベントの処理
document.getElementById('hello-btn').addEventListener('click', () => {
  const messages = [
    'こんにちは!Electronの世界へようこそ!',
    'ボタンがクリックされました!',
    'デスクトップアプリケーション開発は楽しいですね!',
    'もう一度クリックしてみてください!'
  ]
  
  // ランダムなメッセージを表示
  const randomMessage = messages[Math.floor(Math.random() * messages.length)]
  document.getElementById('message').textContent = randomMessage
  
  // 3秒後にメッセージを消す
  setTimeout(() => {
    document.getElementById('message').textContent = ''
  }, 3000)
})

このコードでは、ボタンがクリックされたときにランダムなメッセージを表示し、3秒後に自動的に消える機能を実装しています。これにより、ユーザーとのインタラクションが可能になります。

メニューバーの追加

デスクトップアプリケーションらしくするため、メニューバーを追加します。main.jsに以下のコードを追加します:

javascript
// main.jsの先頭に追加
const { app, BrowserWindow, Menu } = require('electron')

// createWindow関数の後に追加
function createMenu() {
  const template = [
    {
      label: 'ファイル',
      submenu: [
        {
          label: '新規作成',
          accelerator: 'CmdOrCtrl+N',
          click: () => {
            console.log('新規作成がクリックされました')
          }
        },
        { type: 'separator' },
        {
          label: '終了',
          accelerator: process.platform === 'darwin' ? 'Cmd+Q' : 'Ctrl+Q',
          click: () => {
            app.quit()
          }
        }
      ]
    },
    {
      label: '編集',
      submenu: [
        { label: 'コピー', accelerator: 'CmdOrCtrl+C', role: 'copy' },
        { label: 'ペースト', accelerator: 'CmdOrCtrl+V', role: 'paste' }
      ]
    },
    {
      label: 'ヘルプ',
      submenu: [
        {
          label: 'バージョン情報',
          click: () => {
            console.log('Electron Hello World v1.0.0')
          }
        }
      ]
    }
  ]

  const menu = Menu.buildFromTemplate(template)
  Menu.setApplicationMenu(menu)
}

// app.whenReady()内のcreateWindow()の後に追加
app.whenReady().then(() => {
  createWindow()
  createMenu() // この行を追加
  
  // 既存のコード...
})

このコードでは、ファイル、編集、ヘルプの3つのメニューを作成しています。各メニュー項目には、キーボードショートカット(accelerator)や、クリック時の動作を定義できます。

ビルドと配布の準備

ディレクトリ構造の整理

アプリケーションが大きくなってくると、ファイルの整理が重要になります。推奨されるディレクトリ構造:

code
my-electron-app/
├── package.json
├── main.js
├── preload.js
├── src/
│   ├── index.html
│   ├── renderer.js
│   └── styles/
│       └── main.css
├── assets/
│   └── icons/
└── README.md

この構造により、メインプロセスのファイルとレンダラープロセスのファイルが明確に分離され、管理しやすくなります。

アプリケーションアイコンの設定

アプリケーションに独自のアイコンを設定することで、よりプロフェッショナルな印象を与えられます。main.jsのBrowserWindowオプションに以下を追加:

javascript
mainWindow = new BrowserWindow({
  width: 800,
  height: 600,
  icon: path.join(__dirname, 'assets/icons/app-icon.png'), // この行を追加
  webPreferences: {
    preload: path.join(__dirname, 'preload.js')
  }
})

アイコンファイルは、各プラットフォームで異なる形式が推奨されます:

  • Windows: .ico形式(複数サイズを含む)
  • macOS: .icns形式
  • Linux: .png形式(512x512推奨)

よくあるエラーと解決方法

モジュールが見つからないエラー

code
Error: Cannot find module 'electron'

このエラーは、Electronが正しくインストールされていない場合に発生します。以下のコマンドで再インストールします:

bash
npm install --save-dev electron

ファイルパスのエラー

code
Failed to load resource: net::ERR_FILE_NOT_FOUND

このエラーは、HTMLやJavaScriptファイルのパスが間違っている場合に発生します。ファイル名の大文字小文字や、相対パスが正しいか確認してください。

セキュリティ警告

code
Electron Security Warning (Insecure Content-Security-Policy)

この警告は、セキュリティ設定が不適切な場合に表示されます。本番環境では、適切なContent Security Policyを設定することが重要です。

次のステップ

学習を深めるために

Hello Worldアプリケーションの作成に成功したら、以下のような機能を追加して学習を深めることをおすすめします:

  1. ファイル操作: テキストファイルの読み書き機能
  2. データ保存: localStorageやファイルシステムを使用したデータの永続化
  3. 外部API連携: Web APIからデータを取得して表示
  4. マルチウィンドウ: 複数のウィンドウを管理する機能
  5. システムトレイ: タスクバーに常駐するアプリケーション

より実践的なプロジェクト

基本を理解したら、以下のような実践的なプロジェクトに挑戦してみましょう:

シンプルなメモ帳アプリ: テキストエディタの基本機能(新規作成、開く、保存)を実装

画像ビューアー: 画像ファイルをドラッグ&ドロップで表示し、簡単な編集機能を追加

ToDoリストアプリ: タスクの追加、削除、完了状態の管理機能を実装

時計・タイマーアプリ: デスクトップウィジェットとして使える時計やタイマー

これらのプロジェクトを通じて、Electronの様々な機能を実践的に学ぶことができます。

まとめ

本記事では、Electronを使った最初のデスクトップアプリケーション「Hello World」の作成方法を詳しく解説しました。環境構築から始まり、基本的なプロジェクト構造の理解、メインプロセスとレンダラープロセスの実装、そして実際の起動まで、一つ一つのステップを丁寧に説明しました。

Electronの魅力は、Web開発の知識をそのまま活かせることです。HTML、CSS、JavaScriptという馴染みのある技術で、Windows、macOS、Linuxで動作するデスクトップアプリケーションを作成できることは、開発者にとって大きなメリットです。

このHello Worldアプリケーションは、Electron開発の第一歩に過ぎません。ここで学んだ基礎知識を土台に、より複雑で実用的なアプリケーションの開発に挑戦してください。メニューバーやダイアログ、ファイル操作、データベース連携など、Electronには豊富な機能が用意されています。

開発中に問題に直面した時は、公式ドキュメントやコミュニティのサポートを活用しましょう。エラーメッセージを理解し、一つ一つ解決していくことで、確実にスキルアップできます。

最後に、作成したアプリケーションを実際に使ってもらうことを目標に開発を続けてください。ユーザーのフィードバックを受けて改善していくことで、より良いアプリケーションを作ることができるでしょう。Electronでのデスクトップアプリケーション開発の旅を、ぜひ楽しんでください。