【初心者向け】Electron で始めるデスクトップアプリ開発 #3
はじめに
前回(#2)は、セクション 2:アプリ構成とファイル準備 と題して、アプリの基本構成、UI(インターフェース)用のファイル `index.html`、`style.css` についてお話しました。
今回はそれに続き、Electron アプリの中核を担う `main.js`、`preload.js`、`renderer.js` を取り上げます。
実行環境
以下の環境で、お伝えする内容を検証しています。
OS:Microsoft Windows 11 Homeバージョン:10.0.26100 Build 26100
Node.js:v22.14.0
npm:v11.2.0
PowerShell:7.5.0
シェル:Microsoft.PowerShell
CPU:AMD64 Family 25 Model 80 / 2GHz
エディタ:Visual Studio Code 1.98.2
⚠️ 本記事では、Node.js、npm、Visual Studio Code のインストール手順や、エラーメッセージ などへの対応については扱いません。これらが正常に動作していることを前提として、Electron アプリ開発の手順を解説しています。
🔸 セクション 3:Electron のメイン機能実装
3-1. ⚙️ main.js
役割:Electronの中枢、ウィンドウ管理とCLI実行
アプリの起動・ウィンドウ生成を管理
CLIスクリプトを spawn で起動
実行結果をレンダラープロセスに送信
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const { spawn } = require('child_process');
let win;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
enableRemoteModule: false,
nodeIntegration: false
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
ipcMain.on('start-cli', () => {
const cliPath = path.join(__dirname, 'cli-script.js');
const cli = spawn('node', [cliPath]); // node.js で cli-script.js を実行する
cli.stdout.on('data', (data) => { // 通常の受け取り
win.webContents.send('cli-log', data.toString());
});
cli.stderr.on('data', (data) => { // エラーの受け取り
win.webContents.send('cli-log', `[stderr] ${data.toString()}`);
});
cli.on('close', (code) => { // 終了コードの受け取り
win.webContents.send('cli-log', `\n[CLI 終了: code ${code}]`);
});
});💡 ワンポイント
1. webPreferences のオプションについて
Electron では、「メインプロセス(アプリの中枢)」 と 「レンダラープロセス(画面表示)」 に役割が分かれています。
これらのオプションは、画面側(レンダラー)が 勝手にメインの操作をしないようにする ための設定です。
preload: path.join(__dirname, 'preload.js') → Preload スクリプトの指定
preload.js(後述)は、レンダラープロセスとメインプロセスをつなぐ役割を持ちます。
preload.js を通して、安全に通信することを宣言します。
contextIsolation: true → レンダラープロセスからメインプロセスを直接操作できないようにする
true にすると、レンダラープロセスの JavaScript からメインプロセスへ直接アクセスできなくなります。
これにより、セキュリティを強化できます。
enableRemoteModule: false → remote モジュールの無効化
以前の Electron には remote という、メインプロセスを直接操作できる機能がありました。
これを無効化することで、安全性を高めます。
nodeIntegration: false → レンダラープロセスで Node.js を無効化
true にすると、レンダラープロセスから Node.js の機能(例: fs など)が直接使えてしまいます。
false にすることで、preload.js を介した通信の原則を守り、リスクを減らせます。
2. data.toString() について
spawn で起動したプロセスの stdout や stderr は Buffer(バイナリデータなどを格納できるオブジェクト) として送られます。
data.toString() を使うことで、これを 通常の文字列 に変換できます。
もし、Buffer のままだとどうなる?
cli.stdout.on('data', (data) => {
console.log(data);
});このままだと、<Buffer 48 65 6c 6c 6f> のような表示になってしまいます。
.toString() を使えば、"Hello" という文字列として扱えます。
3-2. 📡 preload.js
役割:セキュアな橋渡し(Renderer と Mainの中継)
Renderer から直接 Node.js にアクセスできない代わりに使う
contextBridge を使って機能を露出
双方向通信の「安全な窓口」
contextBridge.exposeInMainWorld('electronAPI', {
startCLI: () => ipcRenderer.send('start-cli'),
onLog: (cb) => ipcRenderer.on('cli-log', (_e, log) => cb(log))
});3-3. 🖼️ renderer.js
役割:UI操作・イベント処理・ログ表示制御
ボタン押下イベントを検知し Preload 経由でCLIを開始
ログを受け取り、#log に追記
UIの状態を動的に更新
const runBtn = document.getElementById('run-btn');
const logArea = document.getElementById('log');
runBtn.addEventListener('click', () => {
logArea.textContent = '実行中...\n';
window.electronAPI.startCLI();
});
window.electronAPI.onLog((log) => {
logArea.textContent += log;
logArea.scrollTop = logArea.scrollHeight;
});📌 おわりに
前回作成した、index.html と style.css 。
今回作成した main.js、preload.js、renderer.js も加わり、Electron の主要なファイルが揃いました。
次回は、Electron から呼び出される cli-script.js を作り、package.json を更新して、いよいよ アプリを動かします。お楽しみに!
参考:Electron 公式サイト https://www.electronjs.org/ja/
👉 次回(#4)はこちらから、どうぞ
👉 まとめ記事はこちらから、どうぞ
👉 記事一覧(マガジン)は、こちらから、どうぞ
✍️ この記事が参考になったら──
筆者ふじけんのことが少しわかる、自己紹介noteもぜひどうぞ:
→ 🎰 777の日に、自己紹介してみた(100日投稿を超えて)(2025-07-07)
→ 気づけば続いてた。40,000views、ChatGPT1周年、そして256日連続。(2025-12-04)
いいなと思ったら応援しよう!
読んでくださってありがとうございます。
最後までお付き合いいただけて感謝です。
いただいたチップはクリエイターとしての活動費に使わせていただきます! 