Electron
ChromiumとNode.jsを基盤とするクロスプラットフォームデスクトップアプリフレームワーク。Web技術(HTML、CSS、JavaScript)でネイティブアプリを開発可能。Visual Studio Code、Discord、Slackなど多くの著名アプリケーションで採用。
GitHub概要
electron/electron
:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS
トピックス
スター履歴
フレームワーク
Electron
概要
ElectronはChromiumブラウザエンジンとNode.jsランタイムを組み合わせたクロスプラットフォームデスクトップアプリ開発フレームワークです。Web技術でネイティブアプリを構築できます。
詳細
Electron(エレクトロン)は、Web技術(HTML、CSS、JavaScript)を使用してクロスプラットフォームデスクトップアプリケーションを構築するための強力なフレームワークです。GitHub(現Microsoft)によって開発され、Visual Studio Code、Slack、Discord、WhatsApp Desktop、Spotify、Figmaなど、数多くの著名なアプリケーションで採用されています。
2025年現在、デスクトップアプリ開発において最も成熟したエコシステムを持ち、Web開発者が既存のスキルを活用してデスクトップアプリを作成できる最有力の選択肢となっています。Node.jsの豊富なエコシステムを活用でき、ネイティブAPIへのアクセス、ファイルシステム操作、システム通知、メニューバー統合などが可能です。
一方で、ChromiumとNode.jsを内包するため、アプリケーションのサイズが大きくなり、メモリ使用量も多くなるという課題が指摘されることがあります。しかし、その開発効率の高さと豊富な機能から、多くの企業や開発者に選ばれ続けています。
メリット・デメリット
メリット
- Web技術活用: HTML/CSS/JavaScriptの既存スキルをそのまま利用
- クロスプラットフォーム: Windows、macOS、Linuxで同一コードが動作
- 豊富なエコシステム: npmの膨大なパッケージライブラリを活用可能
- ネイティブAPI: ファイルシステム、通知、メニューなどOSネイティブ機能にアクセス
- 成熟したツール: 充実した開発ツール、デバッグ環境、パッケージング
- 大手企業採用: VS Code、Slack、Discordなど実績豊富
- 活発なコミュニティ: 世界規模の開発者コミュニティとサポート
デメリット
- リソース使用量: メモリ消費とディスク容量が大きい
- 起動時間: ネイティブアプリに比べて起動が遅い場合
- パフォーマンス: CPU集約的タスクでは劣る可能性
- セキュリティ: Web技術由来のセキュリティ考慮事項
- バンドルサイズ: 配布パッケージサイズが大きい
主要リンク
- Electron公式サイト
- Electron公式ドキュメント
- Electron Forge
- Electron Builder
- Electron GitHub リポジトリ
- Electron コミュニティ
書き方の例
基本的なElectronアプリ
// main.js
const { app, BrowserWindow } = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
win.loadFile('index.html');
};
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
HTMLファイル
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello Electron!</title>
</head>
<body>
<h1>Hello World!</h1>
<p>We are using Node.js <span id="node-version"></span></p>
<p>Chromium <span id="chrome-version"></span></p>
<p>and Electron <span id="electron-version"></span></p>
<script src="renderer.js"></script>
</body>
</html>
レンダラープロセス
// renderer.js
document.getElementById('node-version').innerText = process.versions.node;
document.getElementById('chrome-version').innerText = process.versions.chrome;
document.getElementById('electron-version').innerText = process.versions.electron;
メニューバーの作成
// main.js
const { app, BrowserWindow, Menu } = require('electron');
const template = [
{
label: 'ファイル',
submenu: [
{
label: '新規作成',
accelerator: 'CmdOrCtrl+N',
click: () => {
console.log('新規作成がクリックされました');
}
},
{
label: '開く',
accelerator: 'CmdOrCtrl+O',
click: () => {
console.log('開くがクリックされました');
}
},
{ type: 'separator' },
{
label: '終了',
accelerator: process.platform === 'darwin' ? 'Cmd+Q' : 'Ctrl+Q',
click: () => {
app.quit();
}
}
]
},
{
label: '編集',
submenu: [
{ role: 'undo', label: '元に戻す' },
{ role: 'redo', label: 'やり直し' },
{ type: 'separator' },
{ role: 'cut', label: '切り取り' },
{ role: 'copy', label: 'コピー' },
{ role: 'paste', label: '貼り付け' }
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
ファイルダイアログ
// main.js
const { app, BrowserWindow, dialog, ipcMain } = require('electron');
const fs = require('fs');
ipcMain.handle('open-file-dialog', async () => {
const result = await dialog.showOpenDialog({
properties: ['openFile'],
filters: [
{ name: 'テキストファイル', extensions: ['txt'] },
{ name: 'すべてのファイル', extensions: ['*'] }
]
});
if (!result.canceled) {
const filePath = result.filePaths[0];
const content = fs.readFileSync(filePath, 'utf-8');
return { filePath, content };
}
return null;
});
プリロードスクリプト(セキュア版)
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
openFile: () => ipcRenderer.invoke('open-file-dialog'),
onMenuClick: (callback) => ipcRenderer.on('menu-click', callback),
platform: process.platform,
versions: process.versions
});
レンダラーでAPIを使用
// renderer.js
document.addEventListener('DOMContentLoaded', () => {
// ファイルを開くボタン
document.getElementById('open-file').addEventListener('click', async () => {
const result = await window.electronAPI.openFile();
if (result) {
document.getElementById('file-content').textContent = result.content;
document.getElementById('file-path').textContent = result.filePath;
}
});
// バージョン情報を表示
document.getElementById('platform').textContent = window.electronAPI.platform;
document.getElementById('versions').textContent =
JSON.stringify(window.electronAPI.versions, null, 2);
});
通知の表示
// main.js
const { app, BrowserWindow, Notification } = require('electron');
function showNotification() {
new Notification({
title: 'Electronアプリ',
body: 'これは通知メッセージです!',
icon: 'assets/icon.png'
}).show();
}
app.whenReady().then(() => {
createWindow();
showNotification();
});
package.jsonの設定
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder",
"dist": "electron-builder --publish=never"
},
"author": "Your Name",
"license": "MIT",
"devDependencies": {
"electron": "^23.0.0",
"electron-builder": "^23.0.0"
}
}
プロジェクト作成と実行
# 新しいディレクトリを作成
mkdir my-electron-app && cd my-electron-app
# npm プロジェクトを初期化
npm init -y
# Electronを開発依存関係としてインストール
npm install electron --save-dev
# アプリケーションを実行
npm start
# Electron Forgeでプロジェクト作成(推奨)
npm install -g @electron-forge/cli
electron-forge init my-app
cd my-app
npm start
# アプリケーションをパッケージ化
npm run make