Electron セットアップ最短ルート:Vite + TypeScript + ESLint + Preload 分離

Electron アプリ開発において、従来の Webpack ベースの環境構築は複雑で時間がかかるものでした。しかし、現在ではVite + TypeScript + ESLintの組み合わせにより、セキュリティを保ちながら最短ルートでの開発環境構築が可能です。
この記事では、最新のツールチェーンを活用して効率的な Electron アプリ開発環境を構築する手順をわかりやすく解説いたします。特にPreload スクリプトの適切な分離も含めて、実践的なセットアップ方法をご紹介いたします。
背景
従来の Electron セットアップの煩雑さ
Electron アプリ開発の従来のアプローチでは、Webpack の複雑な設定が必要でした。メインプロセス、レンダラープロセス、Preload スクリプトのそれぞれに異なる設定が必要で、初心者にとっては非常に高いハードルとなっていました。
設定ファイルが複数に分かれ、依存関係の管理も煩雑になりがちでした。また、開発サーバーの起動に時間がかかり、コード変更時のホットリロードも遅いという問題がありました。
Vite 登場による開発体験の向上
2020 年にリリースされた Vite は、ES Modules を活用した高速な開発サーバーを提供します。従来の Webpack と比較して、以下の図のような大幅な改善を実現しています。
mermaidflowchart LR
webpack["Webpack<br/>バンドル型"] -->|"遅い"| dev1["開発サーバー<br/>起動時間: 数分"]
vite["Vite<br/>ESM型"] -->|"高速"| dev2["開発サーバー<br/>起動時間: 数秒"]
dev1 --> reload1["ホットリロード<br/>数秒〜数十秒"]
dev2 --> reload2["ホットリロード<br/>ミリ秒単位"]
この図が示すように、Vite を使用することで開発効率が劇的に向上しています。
TypeScript 導入による型安全性の重要性
Electron アプリでは、メインプロセスとレンダラープロセス間での IPC 通信が頻繁に発生します。このような複雑な処理において、型安全性は非常に重要です。
TypeScript を導入することで、コンパイル時にエラーを検出でき、実行時エラーを大幅に減らすことができます。特に、Electron の複雑な API 呼び出しにおいて、型補完により開発者の生産性も向上します。
セキュリティ観点からの Preload 分離の必要性
Electron アプリのセキュリティにおいて Preload スクリプトの適切な分離は必須です。Context Isolation を有効にし、Preload スクリプトを通じて安全に Node.js API にアクセスする仕組みを構築する必要があります。
以下の図は、安全なアーキテクチャの基本構造を示しています。
mermaidflowchart TD
renderer["レンダラープロセス<br/>(Webページ)"] --> preload["Preloadスクリプト<br/>(分離された環境)"]
preload --> main["メインプロセス<br/>(Node.js API)"]
renderer -.->|"直接アクセス禁止"| main
subgraph "Context Isolation"
preload
end
subgraph "セキュリティ境界"
renderer
end
この分離により、レンダラープロセスから直接 Node.js API にアクセスすることを防ぎ、セキュリティリスクを大幅に軽減できます。
課題
従来の Webpack ベースセットアップの複雑性
従来の Electron アプリ開発では、Webpack の設定が非常に複雑でした。メインプロセス用、レンダラープロセス用、Preload スクリプト用の 3 つの異なる設定ファイルが必要で、それぞれに異なるローダーやプラグインの設定が求められます。
この複雑性により、プロジェクトの初期セットアップに多大な時間がかかり、設定ミスによるトラブルも頻発していました。特に初心者にとっては、どの設定がどのプロセスに影響するかを理解することが困難でした。
開発サーバーの起動時間の長さ
Webpack ベースの開発環境では、初回起動時にすべてのモジュールをバンドルする必要があります。プロジェクトが大きくなるにつれて、この処理に数分かかることも珍しくありませんでした。
コード変更時のホットリロードも同様に時間がかかり、開発者の集中力を削ぐ要因となっていました。以下の表は、プロジェクトサイズごとの起動時間の目安を示しています。
プロジェクトサイズ | Webpack 起動時間 | Vite 起動時間 |
---|---|---|
小規模(~50 ファイル) | 30 秒〜1 分 | 2〜5 秒 |
中規模(~200 ファイル) | 1〜3 分 | 3〜8 秒 |
大規模(500 ファイル+) | 3〜10 分 | 5〜15 秒 |
TypeScript 設定の難しさ
Electron アプリで TypeScript を使用する場合、メインプロセスとレンダラープロセスで異なる実行環境に対応する必要があります。Node.js 環境のメインプロセスとブラウザ環境のレンダラープロセスでは、利用可能な API が大きく異なるためです。
適切な型定義ファイルの設定や、プロセス間での型共有の仕組みを構築することは、経験豊富な開発者でも時間がかかる作業でした。
Preload スクリプトの適切な分離方法の不明瞭さ
Electron のセキュリティベストプラクティスでは、Preload スクリプトを使用してレンダラープロセスとメインプロセス間の安全な通信を実現する必要があります。しかし、どのように実装すべきかが不明瞭で、多くの開発者が適切でない方法を採用してしまうケースが見られました。
特に以下のような問題が頻発していました:
- Context Isolation の設定不備
- 不適切な IPC 通信の実装
- セキュリティホールを生む危険な直接アクセス
これらの課題により、安全で効率的な Electron アプリの開発は非常に困難なものとなっていました。
解決策
Vite を活用した高速開発環境の構築
Vite の導入により、従来の Webpack ベースの複雑な設定を大幅に簡素化できます。Vite は設定ゼロでも動作するため、最小限の設定で Electron アプリの開発を開始できます。
以下の図は、Vite ベースの新しい開発フローを示しています。
mermaidflowchart TB
start["プロジェクト開始"] --> install["yarn create electron-vite"]
install --> config["簡単な設定<br/>(1ファイルのみ)"]
config --> dev["yarn dev<br/>(数秒で起動)"]
dev --> coding["コーディング"]
coding --> hmr["HMR<br/>(瞬時に反映)"]
hmr --> coding
この図で分かるように、Vite ベースのワークフローは非常にシンプルで効率的です。
Vite の主な利点は以下の通りです:
- 高速な開発サーバー起動: ES Modules を活用し、数秒で起動
- 瞬時のホットモジュールリプレースメント: コード変更が即座に反映
- 最小限の設定: 複雑な Webpack 設定が不要
- 豊富なプラグインエコシステム: TypeScript、ESLint などの統合が簡単
TypeScript による型安全なコード品質の確保
TypeScript の導入により、Electron アプリ特有の複雑なプロセス間通信においても型安全性を確保できます。特に重要なのは、IPC 通信における型共有の仕組みです。
型安全性の確保により以下のメリットが得られます:
- コンパイル時エラー検出: 実行前にバグを発見
- 優れた開発者体験: 型補完によるコーディング効率向上
- リファクタリングの安全性: 大規模な変更でも型チェックで安心
- ドキュメント代わり: 型定義自体が API ドキュメントの役割
ESLint によるコード品質管理
ESLint の設定により、チーム開発における一貫したコード品質を維持できます。特に Electron アプリでは、セキュリティに関するルールセットの適用が重要です。
推奨する設定の組み合わせは以下の通りです:
設定項目 | 推奨パッケージ | 目的 |
---|---|---|
基本ルール | @typescript-eslint/recommended | TypeScript 基本ルール |
セキュリティ | eslint-plugin-security | セキュリティホール検出 |
Electron 固有 | eslint-plugin-electron | Electron 特有の問題対応 |
インポート管理 | eslint-plugin-import | モジュール管理の最適化 |
セキュリティベストプラクティスに基づく Preload 分離
適切な Preload スクリプトの分離により、セキュリティを保ちながら必要な機能にアクセスできる仕組みを構築します。以下の図は、推奨するアーキテクチャパターンを示しています。
mermaidflowchart LR
subgraph "レンダラープロセス"
web["Webアプリ<br/>(React/Vue等)"]
end
subgraph "Preload領域"
api["window.electronAPI<br/>(型安全なAPI)"]
end
subgraph "メインプロセス"
main["Node.js API<br/>(ファイルシステム等)"]
end
web --> api
api --> main
main --> api
api --> web
この構成により、以下のセキュリティ要件を満たします:
- Context Isolation 有効: レンダラープロセスの完全分離
- Node Integration 無効: 直接的な Node.js API アクセスを禁止
- 型安全な API: Preload を通じた制御されたアクセス
- 最小権限の原則: 必要最小限の機能のみ公開
具体例
それでは、実際に Vite + TypeScript + ESLint + Preload 分離を活用した Electron アプリを構築していきましょう。順を追って詳しく解説いたします。
プロジェクト初期化
まず、プロジェクトの初期化から始めます。electron-vite テンプレートを使用することで、最短時間でのセットアップが可能です。
bash# プロジェクトの作成
yarn create electron-vite my-electron-app
cd my-electron-app
この一つのコマンドで、以下の構成が自動的に作成されます:
- Vite 設定ファイル
- TypeScript 設定
- 基本的な ESLint 設定
- Electron の基本構造
作成されるディレクトリ構造は以下のようになります:
perlmy-electron-app/
├── src/
│ ├── main/ # メインプロセス
│ ├── preload/ # Preloadスクリプト
│ └── renderer/ # レンダラープロセス
├── electron.vite.config.ts
├── package.json
└── tsconfig.json
Vite 設定
electron.vite.config.ts ファイルで Vite の設定を行います。このファイル一つで全プロセスの設定を管理できるのが Vite の大きな利点です。
typescriptimport { resolve } from 'path';
import {
defineConfig,
externalizeDepsPlugin,
} from 'electron-vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
},
preload: {
plugins: [externalizeDepsPlugin()],
},
renderer: {
resolve: {
alias: {
'@renderer': resolve('src/renderer/src'),
},
},
plugins: [react()],
},
});
この設定により、以下の機能が有効になります:
- externalizeDepsPlugin: Node.js 依存関係の外部化
- エイリアス設定: インポートパスの簡略化
- React 統合: レンダラープロセスで React を使用可能
TypeScript 設定
TypeScript の設定では、各プロセスに応じた適切な型環境を構築します。tsconfig.json ファイルを以下のように設定します:
json{
"extends": "@electron-toolkit/tsconfig/tsconfig.json",
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@main/*": ["src/main/*"],
"@preload/*": ["src/preload/*"],
"@renderer/*": ["src/renderer/*"]
}
},
"include": ["src/**/*", "electron.vite.config.*"]
}
各プロセス専用の型定義ファイルも作成します:
typescript// src/types/electron.d.ts
export interface IElectronAPI {
openFile: () => Promise<string>;
saveFile: (content: string) => Promise<void>;
onMenuClick: (callback: (menuId: string) => void) => void;
}
declare global {
interface Window {
electronAPI: IElectronAPI;
}
}
この設定により、レンダラープロセスから Preload API に型安全にアクセスできるようになります。
ESLint 設定
セキュリティとコード品質を重視した ESLint 設定を行います。.eslintrc.js ファイルを以下のように設定します:
javascriptmodule.exports = {
extends: [
'@electron-toolkit/eslint-config-ts',
'@electron-toolkit/eslint-config-prettier',
],
rules: {
// Electron特有のセキュリティルール
'@typescript-eslint/explicit-function-return-type':
'error',
'import/no-nodejs-modules': [
'error',
{
allow: ['path', 'fs'],
},
],
// 危険なAPIの使用を禁止
'no-eval': 'error',
'no-implied-eval': 'error',
},
};
package.json に lint スクリプトを追加します:
json{
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
}
}
Preload 分離実装
最も重要な Preload スクリプトの実装を行います。セキュリティを保ちながら必要な機能を提供する仕組みを構築します。
まず、メインプロセスでの IPC 設定を行います:
typescript// src/main/index.ts
import {
app,
shell,
BrowserWindow,
ipcMain,
dialog,
} from 'electron';
import { join } from 'path';
import {
electronApp,
optimizer,
is,
} from '@electron-toolkit/utils';
import icon from '../../resources/icon.png?asset';
function createWindow(): void {
const mainWindow = new BrowserWindow({
width: 900,
height: 670,
show: false,
autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}),
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false,
contextIsolation: true,
nodeIntegration: false,
},
});
mainWindow.on('ready-to-show', () => {
mainWindow.show();
});
// IPCハンドラーの設定
ipcMain.handle('dialog:openFile', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Text Files', extensions: ['txt'] },
],
});
return result.filePaths[0];
});
}
次に、Preload スクリプトで安全な API を提供します:
typescript// src/preload/index.ts
import { contextBridge, ipcRenderer } from 'electron';
import { electronAPI } from '@electron-toolkit/preload';
// セキュリティを重視したAPI設計
const api = {
openFile: (): Promise<string> =>
ipcRenderer.invoke('dialog:openFile'),
saveFile: (content: string): Promise<void> =>
ipcRenderer.invoke('dialog:saveFile', content),
onMenuClick: (
callback: (menuId: string) => void
): void => {
ipcRenderer.on('menu-click', (_event, menuId) =>
callback(menuId)
);
},
removeAllListeners: (channel: string): void => {
ipcRenderer.removeAllListeners(channel);
},
};
// 型安全なAPIの公開
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld(
'electron',
electronAPI
);
contextBridge.exposeInMainWorld('electronAPI', api);
} catch (error) {
console.error(error);
}
} else {
window.electron = electronAPI;
window.electronAPI = api;
}
レンダラープロセスでの使用例は以下の通りです:
typescript// src/renderer/src/App.tsx
import React, { useState } from 'react';
function App(): JSX.Element {
const [fileContent, setFileContent] =
useState<string>('');
const handleOpenFile = async (): Promise<void> => {
try {
const filePath = await window.electronAPI.openFile();
if (filePath) {
// ファイルの内容を読み込む処理
console.log('Selected file:', filePath);
}
} catch (error) {
console.error('File open error:', error);
}
};
return (
<div className='container'>
<h1>Electron + Vite + TypeScript App</h1>
<button onClick={handleOpenFile}>
ファイルを開く
</button>
<textarea
value={fileContent}
onChange={(e) => setFileContent(e.target.value)}
placeholder='ファイルの内容がここに表示されます'
/>
</div>
);
}
export default App;
動作確認
セットアップが完了したら、以下のコマンドで動作確認を行います:
bash# 依存関係のインストール
yarn install
# 開発サーバーの起動
yarn dev
# リンティングチェック
yarn lint
# ビルドテスト
yarn build
正常に動作すれば、以下の要素が確認できるはずです:
確認項目 | 期待する結果 |
---|---|
起動時間 | 5 秒以内での起動 |
ホットリロード | コード変更の即座反映 |
型チェック | TypeScript エラーの検出 |
リンティング | ESLint ルールの適用 |
セキュリティ | Context Isolation の有効化 |
図で理解できる要点:
- Vite ベースのワークフローは設定が簡単で高速動作を実現
- Preload アーキテクチャによりセキュリティと機能性を両立
- TypeScript 統合により型安全な開発環境を構築
まとめ
最短ルートでの環境構築メリット
本記事でご紹介した Vite + TypeScript + ESLint + Preload 分離の組み合わせにより、従来の Electron アプリ開発における課題を大幅に解決できることが分かりました。
最も重要なメリットはセットアップ時間の劇的な短縮です。従来の Webpack ベースでは数時間から数日かかっていた環境構築が、わずか数分で完了するようになりました。この時間短縮により、開発者はより価値のあるアプリケーション機能の実装に集中できます。
また、セキュリティ面での改善も大きなポイントです。Preload スクリプトの適切な分離と Context Isolation の活用により、セキュリティリスクを最小限に抑えながら必要な機能を実現できます。これにより、エンタープライズレベルのアプリケーション開発にも安心して適用できるでしょう。
開発体験の向上も見逃せません。Vite の高速なホットリロード、TypeScript の型補完、ESLint によるリアルタイムエラー検出により、開発者のストレスが大幅に軽減されます。
今後の開発効率向上への道筋
このセットアップを基盤として、さらなる開発効率向上を図ることができます。今後検討すべき拡張項目をご紹介いたします。
テスト環境の整備が次のステップとして重要です。Jest、Playwright、または Cypress などのテストフレームワークを導入することで、品質の高いアプリケーションを継続的に開発できるようになります。
CI/CD パイプラインの構築も効果的です。GitHub Actions や GitLab CI を活用して、自動ビルド、テスト、デプロイの仕組みを構築することで、チーム開発における品質管理が格段に向上します。
パフォーマンス監視ツールの導入も考慮すべきでしょう。Electron アプリ特有のメモリ使用量や CPU 負荷を監視する仕組みを構築することで、ユーザー体験の向上につながります。
最後に、チーム開発における標準化も重要な要素です。今回ご紹介した設定をプロジェクトテンプレート化し、組織内での標準的な開発環境として展開することで、チーム全体の生産性向上が期待できます。
このように、Vite + TypeScript + ESLint + Preload 分離の組み合わせは、単なるセットアップの簡素化にとどまらず、長期的な開発効率向上への土台となります。ぜひこのアプローチを活用して、より良い Electron アプリ開発を実現していただければと思います。
関連リンク
公式ドキュメント
- Electron 公式サイト - Electron の最新情報とドキュメント
- Vite 公式サイト - Vite の詳細な設定方法とプラグイン情報
- TypeScript 公式サイト - TypeScript の型システムと設定ガイド
- ESLint 公式サイト - ESLint の設定ルールとプラグイン情報
開発ツール
- electron-vite - Electron アプリ用の Vite プリセット
- electron-toolkit - Electron 開発用のユーティリティライブラリ
- @typescript-eslint - TypeScript 用 ESLint 設定
- Electron Builder - Electron アプリのパッケージング・配布ツール
セキュリティガイド
- Electron セキュリティベストプラクティス - 公式セキュリティガイドライン
- Context Isolation 詳細解説 - セキュアな Preload 実装方法
- Preload Scripts - Preload スクリプトの基本的な使い方
コミュニティリソース
- Electron Discord - Electron コミュニティのディスカッション
- Awesome Electron - Electron に関する有用なリソース集
- Electron Examples - Electron の機能デモサンプル集
- article
Electron セットアップ最短ルート:Vite + TypeScript + ESLint + Preload 分離
- article
Electron vs Tauri vs Flutter Desktop:サイズ/速度/互換を実測比較
- article
Electron トラブルシュート:白画面(White Screen)問題を 3 分で切り分け
- article
Electron 入門 2025:Web 技術でデスクトップアプリを作る全体像
- article
TauriとElectronのパフォーマンス比較
- article
Tauriとは?Electronと何が違うのか徹底解説
- article
【2025 年 10 月版】 Claude Sonnet 4.5 登場! Claude Pro でも使える!Claude Code のアップデート手順まで紹介
- article
Turborepo で Zustand スライスをパッケージ化:Monorepo 運用の初期設定
- article
Nuxt を macOS + yarn で最短構築:ESLint/Prettier/TS 設定まで一気通貫
- article
キャッシュ比較:WordPress で WP Rocket/LiteSpeed/W3TC を検証
- article
Nginx を macOS で本番級に構築:launchd/ログローテーション/権限・署名のベストプラクティス
- article
WebSocket を NGINX/HAProxy で終端する設定例:アップグレードヘッダーとタイムアウト完全ガイド
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来