はじめてのElectronアプリ - Hello Worldから始める開発
はじめてのElectronアプリ - Hello Worldから始める開発
はじめに
プログラミングの学習において、「Hello World」は最初の一歩として長い歴史を持つ伝統的なプログラムです。新しい技術を学ぶ際に、まずは最小限の動作するプログラムを作ることで、その技術の基本的な構造や動作原理を理解できます。
本記事では、Electronを使った最初のデスクトップアプリケーションを作成する過程を、環境構築から実際の実装、そして実行まで丁寧に解説します。プログラミング初心者の方でも迷わないよう、各ステップを詳しく説明していきますので、安心して進めてください。
開発環境の準備
必要なツールのインストール
Electronアプリケーションを開発するには、まず以下のツールをインストールする必要があります。
Node.js
Node.jsは、JavaScriptをブラウザの外で実行するためのランタイム環境です。Electronの実行に必要不可欠なツールです。
インストール手順:
- Node.js公式サイト(nodejs.org)にアクセス
- LTS(Long Term Support)版をダウンロード(安定性を重視)
- ダウンロードしたインストーラーを実行
- インストールウィザードに従って進める
インストールが完了したら、コマンドライン(Windows: コマンドプロンプト、Mac/Linux: ターミナル)で以下のコマンドを実行して、正しくインストールされたことを確認します:
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開発に便利な拡張機能が豊富
- 統合ターミナル機能
- インテリセンス(コード補完)機能
プロジェクトディレクトリの作成
開発を始める前に、プロジェクト用のディレクトリ(フォルダ)を作成します。
# プロジェクトディレクトリを作成
mkdir my-electron-app
# 作成したディレクトリに移動
cd my-electron-app
ディレクトリ名は自由に決められますが、わかりやすい名前を付けることをおすすめします。スペースや日本語は避け、半角英数字とハイフン、アンダースコアのみを使用するのが一般的です。
package.jsonの初期化
Node.jsプロジェクトでは、package.jsonというファイルでプロジェクトの設定や依存関係を管理します。以下のコマンドで初期化します:
npm init -y
-yオプションを付けることで、デフォルト設定で自動的にpackage.jsonが作成されます。作成されたpackage.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をインストールします:
npm install --save-dev electron
このコマンドの各部分の意味:
npm install: パッケージをインストールするコマンド--save-dev: 開発時のみ必要な依存関係として記録electron: インストールするパッケージ名
インストールには数分かかることがあります。完了すると、node_modulesディレクトリが作成され、その中にElectronと関連するパッケージがダウンロードされます。
package.jsonの設定更新
Electronアプリケーションとして動作させるため、package.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というファイルを作成し、以下のコードを記述します:
// 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というファイルを作成し、以下の内容を記述します:
<!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というファイルを作成し、以下の内容を記述します:
// プリロードスクリプト
// レンダラープロセスがロードされる前に実行される
// バージョン情報を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というファイルを作成し、以下の内容を記述します:
// レンダラープロセスのスクリプト
// 通常の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の操作、イベントの処理、タイマーの使用など、ブラウザで利用できる機能をすべて使用できます。
アプリケーションの実行
初回起動
すべてのファイルが準備できたら、いよいよアプリケーションを起動します。ターミナルで以下のコマンドを実行します:
npm start
このコマンドは、package.jsonのscripts.startに定義したelectron .を実行します。正常に起動すると、新しいウィンドウが開き、作成したHTMLページが表示されます。
初回起動時によくある問題と解決方法:
ウィンドウが表示されない場合:
- ファイル名が正しいか確認(main.js、index.html)
- package.jsonのmainフィールドが正しく設定されているか確認
- コンソールにエラーメッセージが表示されていないか確認
白い画面が表示される場合:
- index.htmlのパスが正しいか確認
- HTMLファイルの構文エラーがないか確認
- 開発者ツールでコンソールエラーを確認
開発者ツールの使い方
Electronアプリケーションでは、ChromeのDevToolsを使用してデバッグできます。開発者ツールを開くには、以下の方法があります:
- メニューから開く:View → Toggle Developer Tools
- キーボードショートカット:
- Windows/Linux: Ctrl + Shift + I
- macOS: Cmd + Option + I
- プログラムから開く:main.jsに以下のコードを追加
// main.jsのcreateWindow関数内に追加
mainWindow.webContents.openDevTools()
開発者ツールでは、以下の機能が利用できます:
- Console: JavaScriptのエラーやconsole.logの出力を確認
- Elements: HTMLの構造とCSSを確認・編集
- Sources: JavaScriptのデバッグ(ブレークポイントの設定)
- Network: ネットワークリクエストの監視
- Performance: パフォーマンスの分析
機能の追加と拡張
ボタンによるインタラクション
アプリケーションをより対話的にするため、ボタンを追加してみましょう。index.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に以下のコードを追加します:
// ボタンクリックイベントの処理
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に以下のコードを追加します:
// 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)や、クリック時の動作を定義できます。
ビルドと配布の準備
ディレクトリ構造の整理
アプリケーションが大きくなってくると、ファイルの整理が重要になります。推奨されるディレクトリ構造:
my-electron-app/
├── package.json
├── main.js
├── preload.js
├── src/
│ ├── index.html
│ ├── renderer.js
│ └── styles/
│ └── main.css
├── assets/
│ └── icons/
└── README.md
この構造により、メインプロセスのファイルとレンダラープロセスのファイルが明確に分離され、管理しやすくなります。
アプリケーションアイコンの設定
アプリケーションに独自のアイコンを設定することで、よりプロフェッショナルな印象を与えられます。main.jsのBrowserWindowオプションに以下を追加:
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推奨)
よくあるエラーと解決方法
モジュールが見つからないエラー
Error: Cannot find module 'electron'
このエラーは、Electronが正しくインストールされていない場合に発生します。以下のコマンドで再インストールします:
npm install --save-dev electron
ファイルパスのエラー
Failed to load resource: net::ERR_FILE_NOT_FOUND
このエラーは、HTMLやJavaScriptファイルのパスが間違っている場合に発生します。ファイル名の大文字小文字や、相対パスが正しいか確認してください。
セキュリティ警告
Electron Security Warning (Insecure Content-Security-Policy)
この警告は、セキュリティ設定が不適切な場合に表示されます。本番環境では、適切なContent Security Policyを設定することが重要です。
次のステップ
学習を深めるために
Hello Worldアプリケーションの作成に成功したら、以下のような機能を追加して学習を深めることをおすすめします:
- ファイル操作: テキストファイルの読み書き機能
- データ保存: localStorageやファイルシステムを使用したデータの永続化
- 外部API連携: Web APIからデータを取得して表示
- マルチウィンドウ: 複数のウィンドウを管理する機能
- システムトレイ: タスクバーに常駐するアプリケーション
より実践的なプロジェクト
基本を理解したら、以下のような実践的なプロジェクトに挑戦してみましょう:
シンプルなメモ帳アプリ: テキストエディタの基本機能(新規作成、開く、保存)を実装
画像ビューアー: 画像ファイルをドラッグ&ドロップで表示し、簡単な編集機能を追加
ToDoリストアプリ: タスクの追加、削除、完了状態の管理機能を実装
時計・タイマーアプリ: デスクトップウィジェットとして使える時計やタイマー
これらのプロジェクトを通じて、Electronの様々な機能を実践的に学ぶことができます。
まとめ
本記事では、Electronを使った最初のデスクトップアプリケーション「Hello World」の作成方法を詳しく解説しました。環境構築から始まり、基本的なプロジェクト構造の理解、メインプロセスとレンダラープロセスの実装、そして実際の起動まで、一つ一つのステップを丁寧に説明しました。
Electronの魅力は、Web開発の知識をそのまま活かせることです。HTML、CSS、JavaScriptという馴染みのある技術で、Windows、macOS、Linuxで動作するデスクトップアプリケーションを作成できることは、開発者にとって大きなメリットです。
このHello Worldアプリケーションは、Electron開発の第一歩に過ぎません。ここで学んだ基礎知識を土台に、より複雑で実用的なアプリケーションの開発に挑戦してください。メニューバーやダイアログ、ファイル操作、データベース連携など、Electronには豊富な機能が用意されています。
開発中に問題に直面した時は、公式ドキュメントやコミュニティのサポートを活用しましょう。エラーメッセージを理解し、一つ一つ解決していくことで、確実にスキルアップできます。
最後に、作成したアプリケーションを実際に使ってもらうことを目標に開発を続けてください。ユーザーのフィードバックを受けて改善していくことで、より良いアプリケーションを作ることができるでしょう。Electronでのデスクトップアプリケーション開発の旅を、ぜひ楽しんでください。