electron-dev について
Electron Vite と Electron Builder を使ったアプリ開発向けのスキルです。アーキテクチャ、セキュリティ、IPC、設定、検証の指針を扱います。
主な機能
- 01メイン・レンダラー・プリロードの役割
- 02プロセス間の安全な分離
- 03IPC チャネルの許可リストと検証
- 04electron-vite 設定のガイダンス
- 05ネイティブモジュールのビルドガイダンス
- 06型チェックとテストのチェックリスト
活用シーン
- 01Electron アプリの構成
- 02レンダラーとメイン間の通信保護
- 03ネイティブモジュールのビルド設定
- 04完了前の Electron 変更確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ pedronauck/ skills --skill electron-devインストール後、Claude Code で/electron-devを入力して読み込まれたか確認します。
同梱ファイルreferences/patterns.md
詳細
Electron 開発ガイド
このスキルでは、Electron Vite と Electron Builder を使用して、本番環境向けの高品質な Electron アプリケーションを構築するためのガイドライン、パターン、ベストプラクティスを紹介します。
クイックスタート
- 基本ルール:Electron 開発のパターンとガイドラインの詳細については、このスキル内の
references/patterns.mdを参照してください。 - セキュリティ:常に
contextIsolationとsandboxを有効にし、nodeIntegrationを無効にしてください。 - アーキテクチャ:メインプロセスは Node.js の操作を担当し、レンダラープロセスは UI に専念します。プリロードが両者を安全に橋渡しします。
プロセスアーキテクチャ
メインプロセス(Node.js コンテキスト)
メインプロセスは以下を担当します。
- ウィンドウの作成とライフサイクル管理
- ファイルシステムとデータベースの操作
- IPC メッセージの処理
- アプリケーションレベルのイベント
主なガイドライン:
- ウィンドウを作成する前に
app.isReady()を使用する window.destroyedイベントでリソースをクリーンアップするapp.on('before-quit')で正常にシャットダウンする
レンダラープロセス(フロントエンドコンテキスト)
レンダラープロセスは以下を行います。
- Web 技術(React、Vue など)を使用して UI を描画する
- IPC のみを使用してメインプロセスと通信する
- Node.js API に直接アクセスしない
プリロードスクリプト(セキュリティレイヤー)
プリロードスクリプトは、レンダラープロセスとメインプロセスをつなぐ唯一のブリッジです。
import { contextBridge, ipcRenderer } from "electron";
contextBridge.exposeInMainWorld("electronAPI", {
invoke: (channel: string, args?: unknown) => {
const validChannels = ["db:query", "file:save", "app:close"];
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
throw new Error(`Invalid IPC channel: ${channel}`);
},
});
セキュリティチェックリスト
webPreferences は、常に以下の設定で構成してください。
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // REQUIRED
enableRemoteModule: false, // REQUIRED
sandbox: true, // REQUIRED
nodeIntegration: false, // REQUIRED
webSecurity: true,
}
IPC 通信
メインプロセスのハンドラー
ipcMain.handle("db:insert", async (event, data: unknown) => {
if (!isValidInsertData(data)) {
throw new Error("Invalid data");
}
return db.insert(data);
});
セキュリティルール
- プリロードスクリプトで、すべての IPC チャネルをホワイトリストに登録する
- メインプロセスのハンドラーですべての引数を検証する
- レンダラープロセスからのユーザー入力を決して信頼しない
- シークレットはメインプロセスのみに保持する
設定
electron-vite.config.ts
import { defineConfig } from "electron-vite";
export default defineConfig({
main: {
build: {
outDir: "dist/main",
rollupOptions: {
external: ["better-sqlite3", "native-module-name"],
},
},
},
preload: {
build: { outDir: "dist/preload" },
},
renderer: {
build: {
outDir: "dist/renderer",
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
},
},
},
},
},
});
ネイティブモジュール
better-sqlite3 などのネイティブモジュールの場合:
- electron-vite の設定で rollup の対象から除外する
- Electron Builder の設定で
extraResourcesに含める - メインプロセスで動的インポートを使用する
@electron/rebuildを使用して Electron 向けに再ビルドする
よくある落とし穴
絶対にしてはいけないこと
// Exposing entire Node.js API
contextBridge.exposeInMainWorld("require", require);
// Not validating IPC messages
ipcMain.handle("dangerous", (event, data) => {
fs.writeFileSync(data.path, data.content);
});
// Using __dirname in renderer
const imagePath = `${__dirname}/images/logo.png`;
代わりにこちらを実行する
// Whitelist specific channels
contextBridge.exposeInMainWorld("electronAPI", {
invoke: (channel: string, args: unknown) => {
if (!["safe:channel"].includes(channel)) throw new Error("Invalid");
return ipcRenderer.invoke(channel, args);
},
});
// Validate all arguments
ipcMain.handle("file:write", async (event, { path, content }) => {
if (typeof path !== "string" || typeof content !== "string") {
throw new TypeError("Invalid arguments");
}
// Safe to use
});
検証チェックリスト
Electron に関するタスクを完了する前に、以下を確認してください。
- セキュリティ設定が有効になっている(
contextIsolation、sandbox、nodeIntegrationは無効) - プリロードスクリプトで IPC チャネルがホワイトリストに登録されている
- メインプロセスですべての IPC 引数が検証されている
- ネイティブモジュールがバンドラーの対象から除外され、extraResources に含まれている
- シークレットがメインプロセスのみに保持されている(レンダラープロセスに公開されていない)
- 型チェック(
pnpm run typecheck)とテスト(pnpm run test)を実行する
トラブルシューティング
| 問題 | 解決策 |
|---|---|
| 本番環境で画面が真っ白になる | アセットパスに base: './' が使用されていることを確認し、ビルド出力を検証する |
| ネイティブモジュールが失敗する | rollup の対象から除外し、extraResources に含める |
| IPC が機能しない | プリロードパス、contextIsolation の有効化、チャネルのホワイトリスト登録を確認する |
| HMR が機能しない | -w フラグを付けて実行し、VITE_DEV_SERVER_URL を確認する |
設定例とその他のパターンの詳細については、references/patterns.md を参照してください。
コメント
Markdown 対応