- 技術 💻
Electronとは|使い方・仕組み・安全なIPC・パッケージ化を実例で解説
結論
Electronは、HTML・CSS・JavaScriptでデスクトップアプリを作るフレームワークです。Chromium と Node.js を同梱しています。
この記事でわかること
- 最小アプリ5ファイルとv45.0.0で起動した実物
- 安全なIPCの書き方とエラー原文13件の直し方
- パッケージ化・Fuses・自動更新・Tauriとの違いの表
Electron のアプリは、OS の機能を扱う「メインプロセス」と、画面を描く「レンダラー」に分かれています。2つは preload(橋渡しのスクリプト)と IPC(プロセス間通信)でつながります。
flowchart TD
M[メインプロセス<br>Node.js・OS の機能] -->|ウィンドウを作る| R[レンダラー<br>HTML・CSS・JS の画面]
P[preload<br>contextBridge で窓口] --> R
R -->|IPC で頼む| M
急いでいる人向けに、よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Electronとは | Chromium+Node.js でデスクトップアプリを作る | とは |
| 始め方 | npm i -D electron → npx electron . |
始め方 |
| 最新版 | 45.0.0(Chromium 156・Node.js 24.22.0) | バージョン |
| 画面から Node.js を使う | preload の contextBridge+IPC |
安全なIPC |
| exe・dmg を作る | Electron Forge か electron-builder | パッケージ化 |
| 自動更新 | update-electron-app か electron-updater |
自動更新 |
| Tauri との違い | Tauri は OS の WebView+Rust | 違い |
require is not defined |
画面側には既定で Node.js が無い | エラー |
| 無料か | MIT ライセンスで無料・商用可 | とは |
確認環境:Ubuntu 24.04.4 LTS・Node.js 22.22.2・npm 10.9.7。electron 45.0.0(2026年10月21日に npm で公開)を npm で入れ、最小のアプリを Xvfb 21.1.12 の仮想ディスプレイで起動しました。画面の文字・プロセスの一覧・IPC の結果・エラー文は、起動したアプリから取り出した実物です。パッケージ化は、Electron 本体のフォルダに @electron/asar 4.3.1 で作った app.asar を置く手作業の方法で行い、@electron/fuses 2.1.3 で Fuses を読み書きしました。Electron Forge 8.0.1・electron-builder 26.15.3 の使い方、自動更新、セキュリティの推奨、版ごとのサポート期間は electronjs.org・electronforge.io・electron.build の公式ドキュメントと npm のパッケージ情報、Tauri は v2.tauri.app の公式ドキュメントで確かめました(確認日 2026年10月23日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Electronとは|使い方・仕組み・安全なIPC・パッケージ化を実例で解説」
Electronとは(読み方・できること・無料か)
この節では、Electron が何をするもので、何ができて、お金がかかるのかが分かります。
Electron は、Web の技術(HTML・CSS・JavaScript)で Windows・macOS・Linux のデスクトップアプリを作るためのフレームワークです。 公式サイトは「Electron embeds Chromium and Node.js to bring JavaScript to the desktop.」と説明しています。画面を描くブラウザのエンジン(Chromium)と、ファイルや OS を扱う JavaScript の実行環境(Node.js)を1つのアプリに同梱する仕組みです。
読み方は「エレクトロン」です。英語の electron(電子)と同じつづりですが、この記事の Electron はソフトウェアの名前です。GitHub が自社のエディタ Atom のために作った「Atom Shell」が元で、2015年4月23日の公式ブログ(Electron)で「Atom Shell is now called Electron」と改名が告げられました。
11つのコードで3つの OS
同じ HTML・JS で Windows・macOS・Linux のアプリになる。画面はどの OS でも同梱の Chromium が描く。
2OS の機能を使える
ファイルの読み書き、メニュー、通知、トレイのアイコン、ファイル選択のダイアログなど。ブラウザだけではできないこと。
3Web の資産がそのまま使える
React・Vue・Vite・npm のパッケージを画面づくりに使える。Web 版とコードを共有しやすい。
4配布と更新の道具がある
Electron Forge・electron-builder で exe・dmg・deb を作り、自動更新の仕組みも用意されている。
無料か・商用で使えるか
Electron は MIT ライセンスで、無料で商用のアプリにも使えます。 npm の electron 45.0.0 の license も MIT です。料金のかかるプランはありません。ただし、配布するアプリには Chromium などの同梱物のライセンス表示(Electron のフォルダの LICENSE と LICENSES.chromium.html)が付きます。手元で取り出した 45.0.0 の Linux 版では、LICENSES.chromium.html が 5,598,206 バイトありました。
Electronで作られているアプリの例
公式サイトの「Apps users love, built with Electron」には、次のアプリが並んでいます(2026年10月23日時点)。
| 分野 | アプリ |
|---|---|
| 開発 | VS Code・GitHub Desktop・Postman・MongoDB Compass・Polypane |
| チャット・会議 | Slack・Discord・Signal・Loom・Twitch |
| メモ・タスク | Notion・Obsidian・Trello・Asana |
| デザイン・制作 | Figma・Screen Studio・Splice |
| そのほか | 1Password・Dropbox・Claude・itch・OOMOL Studio |
手元のアプリが Electron 製かどうかは、インストール先に resources/app.asar(macOS では アプリ名.app/Contents/Resources/app.asar)があるかで見分けられます。公式の Application Distribution のページが、アプリのコードをこの場所に置くと説明しているためです(パッケージ化の節で実物を見ます)。Obsidian の使い方は、関連記事「Obsidianとは・使い方|保管庫の中身・同期・料金とNotionとの違い」で扱っています。
Electronの仕組み(メインプロセス・レンダラー・preload・IPC)
この節では、Electron のアプリがどのプロセスで動き、画面と OS の機能がどうつながるのかが分かります。
Electron は Chromium と同じ「複数のプロセス」の作りです。 公式の Process Model のページは、メインプロセスが Chrome の browser プロセスに、レンダラーが Chrome のタブ(renderer プロセス)にあたると説明しています。
| 部品 | どこで動くか | できること | 使える API の例 |
|---|---|---|---|
| メインプロセス | アプリに1つ(Node.js) | ウィンドウの作成、アプリの起動と終了、OS の機能 | app・BrowserWindow・ipcMain・dialog・Menu |
| レンダラー | ウィンドウごとに1つ | 画面を描く。Web の標準どおりに動く | DOM・fetch。既定で require は無い |
| preload | レンダラーの中で、ページより先に動く | ページに安全な窓口を公開する | contextBridge・ipcRenderer |
| ユーティリティプロセス | メインから起動(Node.js) | 重い計算・落ちやすい処理を分ける | utilityProcess |
レンダラーからファイルを読みたいときは、次の順で頼みます。ページは preload が公開した関数を呼び、preload が IPC でメインに送り、メインが Node.js で処理して答えを返します。
flowchart TD
A[ページ<br>window.versions.ping を呼ぶ] --> B[preload<br>ipcRenderer.invoke で送る]
B --> C[メインプロセス<br>ipcMain.handle が処理]
C --> D[戻り値 pong が<br>Promise でページに届く]
この分け方は安全のためです。 画面のページが Node.js を直接使えると、ページに入り込んだスクリプトがファイルを消したり、プログラムを実行したりできてしまいます。そのため Electron は、レンダラーで Node.js を使えない(nodeIntegration: false、5.0.0 から既定)、preload とページの JavaScript の世界を分ける(contextIsolation: true、12.0.0 から既定)、レンダラーをサンドボックスに入れる(sandbox、20.0.0 から既定)の3つを既定にしています(公式の Security のページ)。
Electronの始め方(インストールと最小のアプリ)
この節では、空のフォルダから最小のアプリを作って起動するまでが、実際に動かした出力で分かります。手順は公式チュートリアル(Building your First App・Using Preload Scripts)に沿っています。
Node.js を用意する
electron 45.0.0 の engines は Node.js 22.12.0 以上。Windows では WSL を使わない(公式チュートリアル)。
フォルダを作り npm init
入口(entry point)は main.js。author・description は後のパッケージ化で使う。
electron を devDependencies に入れる
本体はパッケージ化のときに同梱されるので、開発用の依存として入れる。
4つのファイルを書く
main.js・preload.js・index.html・renderer.js。下にそのまま動くコードを載せる。
npm start で起動する
"start": "electron ." を scripts に書く。初回の起動で本体(約124MB)が取得される。
mkdir my-electron-app && cd my-electron-app
npm init -y
npm install --save-dev electron
インストールすると何が入るか(42.0 から初回の起動で取得)
electron 45.0.0 の npm install で入ったのは13個のパッケージ、14MB だけで、Electron 本体はまだありませんでした。 公式の破壊的変更の一覧(Breaking Changes)によると、42.0 から本体は postinstall ではなく、electron コマンドを初めて動かしたときに取得されます。インストール後の node_modules/electron の中身です。
LICENSE README.md abi_version checksums.json cli.js electron.d.ts index.js install.js package.json
本体は GitHub Releases の electron-v45.0.0-linux-x64.zip(123,909,792 バイト)で、取得すると node_modules/electron/dist に展開されます。展開後は 274MB で、そのうち実行ファイル electron が 234,483,016 バイトでした。前もって取得しておきたいときは、公式のインストールのページのとおり npx install-electron --no を使います。
| 環境変数 | 用途(公式のインストールのページ) |
|---|---|
ELECTRON_MIRROR |
取得元の URL を変える(社内のミラーなど) |
electron_config_cache |
取得した zip を置く場所を変える |
ELECTRON_INSTALL_PLATFORM・ELECTRON_INSTALL_ARCH |
別の OS・CPU 用を取る(win32・arm64 など) |
ELECTRON_GET_USE_PROXY |
HTTP プロキシを使う |
取得した zip の置き場所(キャッシュ)は、Linux が ~/.cache/electron/、macOS が ~/Library/Caches/electron/、Windows が %LOCALAPPDATA%\electron\Cache です。
最小のアプリのコード
package.json の main と scripts を次のようにします。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "RJC",
"license": "MIT",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "45.0.0"
}
}
メインプロセスの main.js です。ウィンドウを作り、IPC の受け口(ping)を1つ登録します。
// main.js(メインプロセス)
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('node:path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
ipcMain.handle('ping', () => 'pong')
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
window-all-closed は「最後のウィンドウを閉じたらアプリを終える」(Windows・Linux の流儀)、activate は「Dock のアイコンを押したらウィンドウを作り直す」(macOS の流儀)です。macOS ではウィンドウを閉じてもアプリが残るのが普通なので、darwin(macOS)のときだけ終了しません。
preload で、ページに公開する窓口を決めます。
// preload.js(レンダラーの中で、ページより先に動く)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke('ping')
})
画面の HTML と、画面の JavaScript です。CSP(読み込んでよいスクリプトの決まり)を <meta> で書きます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p id="info"></p>
<p id="pong"></p>
<script src="./renderer.js"></script>
</body>
</html>
// renderer.js(ページの JavaScript。Node.js は使えない)
const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${window.versions.chrome()}), Node.js (v${window.versions.node()}), and Electron (v${window.versions.electron()})`
const func = async () => {
const response = await window.versions.ping()
document.getElementById('pong').innerText = `ping → ${response}`
console.log(response) // 'pong' と出る
}
func()
起動した結果
npm start
起動したウィンドウの文字と、ページの中から調べた値です。
title: Hello from Electron renderer!
info: This app is using Chrome (v156.0.8078.48), Node.js (v24.22.0), and Electron (v45.0.0)
pong: ping → pong
[renderer console] pong
typeof require: undefined
typeof process: undefined
Object.keys(window.versions): node, chrome, electron, ping
typeof window.ipcRenderer: undefined
ページの JavaScript からは require も process も見えず、使えるのは preload が公開した4つの関数だけでした。 ipcRenderer そのものもページには出ていません。それでも ping() を呼ぶと、IPC でメインプロセスまで届き、pong が返りました。
app.getAppMetrics() で見たプロセスの一覧です(ウィンドウ1枚)。
Browser(pid 31803) 145MB, GPU(pid 31830) 57MB, Utility(pid 31833) 77MB, Tab(pid 31850) 87MB
メモリの値は各プロセスの workingSetSize(使っている物理メモリ)で、共有している部分は重ねて数えられます。アプリの大きさのほとんどは Electron 本体(Chromium と Node.js)で、自分のコードは数KB でした。 「Electron のアプリは重い」と言われるのは、この本体をアプリごとに同梱し、Chromium と同じ複数のプロセスで動くためです。
Linux のサーバーや CI のように画面が無いところでは、xvfb-run(仮想のディスプレイ)の上で起動できます。
xvfb-run -a npx electron .
Electronのバージョンとサポート期間
この節では、いまの最新版と、どの版まで修正が出るのかが分かります。
Electron は約8週間ごとに新しいメジャー版が出て、サポートされるのは最新の安定版3つです。 公式の Electron Releases のページは「Electron's cadence between major version releases is 8 weeks long」「The latest three stable major versions are supported」と書いています。2026年10月23日時点の公式のスケジュール(releases.electronjs.org/schedule)です。
| 版 | 安定版の公開 | サポート終了 | Chromium・Node.js |
|---|---|---|---|
| 46.0.0 | 2027年1月5日(予定) | 2027年6月22日(予定) | M160・v24.22.0 |
| 45.0.0 | 2026年10月20日 | 2027年4月27日(予定) | M156・v24.22.0 |
| 44.0.0 | 2026年8月24日 | 2027年3月2日(予定) | M152・v24.18.1 |
| 43.0.0 | 2026年6月29日 | 2027年1月5日(予定) | M150・v24.17.0 |
| 42.0.0 | 2026年5月5日 | 2026年10月20日(終了) | M148・v24.15.0 |
npm の latest は 45.0.0(2026年10月21日公開)で、44 系は 44.9.3、43 系は 43.8.3 が出ています。公式は、各系列で修正が出るのは最新のマイナー版だけとしています。手元の 45.0.0 の実物で確かめた Chromium は 156.0.8078.48、Node.js は 24.22.0 でした。
最近の版の変更で、以前の解説のコードに影響しやすいものです(公式の Breaking Changes)。
| 版 | 変わったこと |
|---|---|
| 45.0 | サンドボックスの preload で events・timers・url と Buffer・setImmediate が使えない |
| 44.0 | レンダラーで clipboard モジュールが使えない(navigator.clipboard に) |
| 44.0 | macOS 12、Windows の 32bit、Linux の armv7l の版が出なくなった |
| 43.0 | ファイルのダイアログの既定の場所が「ダウンロード」に |
| 42.0 | 本体の取得が postinstall から初回の起動時に変わった |
contextIsolationと安全なIPCの書き方(preload・contextBridge)
この節では、画面と OS の機能を安全につなぐ書き方と、やってはいけない書き方の違いが、実際に動かした結果で分かります。
IPCの4つの形
公式の Inter-Process Communication のページは、IPC を4つの形に分けています。
| 形 | レンダラー側 | メイン側 | 使う場面 |
|---|---|---|---|
| レンダラー → メイン(片道) | ipcRenderer.send |
ipcMain.on |
ウィンドウのタイトルを変える |
| レンダラー → メイン(返事あり) | ipcRenderer.invoke |
ipcMain.handle |
ファイルを開いて中身を返す |
| メイン → レンダラー | ipcRenderer.on(preload) |
webContents.send |
メニューから画面に知らせる |
| レンダラー → レンダラー | メインを中継か MessagePort |
― | ウィンドウ同士 |
返事が要るときは invoke と handle を使います。 公式は、以前の send と event.reply の組み合わせや、レンダラーを止めて待つ sendSync を「おすすめしない」形として載せています。
やってはいけない書き方と、安全な書き方
画面からメインの処理を呼びたいとき
nodeIntegration: true・contextIsolation: false にして画面で require する。または ipcRenderer を丸ごと公開するcontextBridge で「用事ごとの関数」だけを公開する。メインで送り元と引数を確かめるページに入り込んだスクリプトが使える範囲を、公開した関数だけに絞る
危ない設定(nodeIntegration: true・contextIsolation: false)でウィンドウを開き、ページの中で調べた結果です。
typeof require: function / typeof process: object / require('node:fs').readdirSync('.').length: 7
ページの JavaScript から Node.js の fs でフォルダの中身が読めました。 この設定で外部のページや、外部の文字列を HTML に入れる画面を開くと、入り込んだスクリプトもファイルを読み書きできます。公式の Context Isolation のページは、ipcRenderer.send をそのまま公開することも「引数を絞らない強力な API」を渡すことになるとして、用事ごとの関数(例:loadPreferences: () => ipcRenderer.invoke('load-prefs'))にする書き方を示しています。
contextBridgeを使わずにwindowに足すと見えない
contextIsolation が有効(既定)のとき、preload で window.myApi = { … } と書いても、ページからは見えません。
typeof window.myApi: undefined
preload とページは同じ window を見ているようで、JavaScript の世界(コンテキスト)が分かれているためです。ページに渡せるのは contextBridge.exposeInMainWorld で公開したものだけです。
メインで送り元と引数を確かめる
公式の Security のページは「Validate the sender of all IPC messages」を挙げ、event.senderFrame を確かめる例を載せています。ローカルの HTML を開くアプリで、送り元のページの URL と引数の型・長さを確かめる例です。
// main.js(抜粋)
const { pathToFileURL } = require('node:url')
const INDEX_URL = pathToFileURL(path.join(__dirname, 'index.html')).href
function isTrustedSender (frame) {
return frame != null && frame.url === INDEX_URL
}
ipcMain.handle('note:save', (event, text) => {
if (!isTrustedSender(event.senderFrame)) throw new Error('untrusted sender')
if (typeof text !== 'string' || text.length > 1000) throw new Error('invalid argument')
return `saved ${text.length} chars`
})
ページから3通りの引数で呼び、その後に別の HTML(nocsp.html)へ移ってから呼んだ結果です。
'こんにちは' → saved 5 chars
123 → Error invoking remote method 'note:save': Error: invalid argument
'x' を2000文字 → Error invoking remote method 'note:save': Error: invalid argument
別のページから呼ぶ → Error invoking remote method 'note:save': Error: untrusted sender
メインで throw したエラーは、レンダラーでは Error invoking remote method '…': が前に付いた文で、Promise の失敗として届きました。手元では event.senderFrame.origin は file://、url は file:///…/index.html だったので、ローカルのファイルの区別には URL を使いました。公式は file:// の代わりに独自のプロトコル(protocol.handle)を使う方法もすすめています。
IPC で送れるのは、構造化複製(structured clone)できる値だけです。 関数を引数に渡すと、レンダラーで次のエラーになりました。DOM の要素や BrowserWindow なども送れません(公式の IPC のページ)。
Uncaught Error: An object could not be cloned.
TypeScriptで公開した関数に型を付ける
公式の Context Isolation のページは、宣言ファイルで Window に型を足す方法を示しています。
// interface.d.ts
export interface IElectronAPI {
loadPreferences: () => Promise<void>
}
declare global {
interface Window {
electronAPI: IElectronAPI
}
}
セキュリティのチェックリスト(公式の20項目から)
公式の Security のページには20項目のチェックリストがあります。最小のアプリでもまず確かめたいものを並べます。
- 1nodeIntegration を有効にしていないか外部の内容を開く画面では特に。有効にするとサンドボックスも外れる
- 2contextIsolation と sandbox を既定のままにしているか公開は contextBridge で、用事ごとの関数だけ
- 3CSP を書いたかscript-src 'self' など。無いと開発中に警告が出る
- 4IPC の送り元と引数を確かめているかevent.senderFrame と、型・長さ・値の範囲
- 5移動・新しいウィンドウを制限したかwill-navigate と setWindowOpenHandler で許す先を決める
- 6shell.openExternal に外部の文字列を渡していないか開く URL は https など許す形だけに
- 7webSecurity を無効にしていないかallowRunningInsecureContent・実験的な機能も有効にしない
- 8サポート中の版を使っているか最新の安定版3つだけに修正が出る
- 9Fuses で使わない機能を切ったかRunAsNode など。パッケージ化の節で実物
CSP の <meta> を書かずに起動すると(環境変数 ELECTRON_ENABLE_SECURITY_WARNINGS=true を付けて起動)、レンダラーのコンソールに次の警告が出ました。
Electron Security Warning (Insecure Content-Security-Policy) This renderer process has either no Content Security
Policy set or a policy with "unsafe-eval" enabled. This exposes users of
this app to unnecessary security risks.
For more information and help, consult
https://electronjs.org/docs/tutorial/security.
This warning will not show up
once the app is packaged.
警告文のとおり、パッケージ化した後は出ません。開発中に消しておくと、出しっぱなしのまま配布することを防げます。CSP の書き方は、関連記事「CSP設定(Content-Security-Policy)|nginx段階導入」で扱っています。
preloadとsandboxで使えるもの
この節では、preload の中で何が使えて何が使えないかと、その理由が分かります。
サンドボックスが有効(20.0.0 から既定)な preload では、require で読めるのは electron(electron/renderer・electron/common)だけです。 公式の Process Sandboxing のページによると、使えるのは contextBridge・crashReporter・ipcRenderer・nativeImage・webFrame・webUtils と、機能を絞った process です。preload で fs を require した結果です。
Unable to load preload script: /…/preload-fs.js
Error: module not found: fs
preload が読み込まれないので、contextBridge で公開するはずだった関数もページから見えなくなりました(typeof window.api が undefined)。同じ preload に sandbox: false を付けると読み込まれ、fs.readdirSync('.') の結果(7)が返りました。
| やりたいこと | 書く場所 |
|---|---|
| ファイルを読む・書く、コマンドを動かす | メインプロセス(ipcMain.handle) |
| 画面に関数を公開する | preload(contextBridge) |
| 画面を描く・ボタンを押す | ページ(renderer.js) |
| 重い計算を分ける | utilityProcess か Web Worker |
| preload を何ファイルかに分ける | バンドラー(Vite・webpack 等)で1つにまとめる |
Node.js の機能はメインプロセスに置き、preload は「窓口」に徹する形が、既定の設定のまま動きます。 公式は、sandbox: false や nodeIntegration: true でサンドボックスを外す方法も載せていますが、外部の内容を扱う画面には使わないよう書いています。サンドボックスの preload ではファイルを require で分けられないので、分けたいときはバンドラーでまとめます。
Electronアプリのパッケージ化(exe・dmg・Electron Forge・electron-builder)
この節では、配布できる形(exe・dmg・deb など)にする方法と、パッケージ化したアプリの中身が、実物で分かります。
パッケージ化したアプリの中身(実物)
パッケージ化は「Electron 本体のフォルダに、自分のコードを resources/app.asar として入れ、実行ファイルの名前を変える」作業です。 公式の Application Distribution のページは、この手作業の方法を説明したうえで、道具として Electron Forge をすすめています。仕組みを確かめるため、最小のアプリを手作業でパッケージ化しました。
npx asar pack ./stage ./out/my-electron-app-linux-x64/resources/app.asar
npx asar list ./out/my-electron-app-linux-x64/resources/app.asar
/index.html
/main.js
/package.json
/preload.js
/renderer.js
asar は、たくさんのファイルを1つにまとめる Electron の形式(tar に似た、圧縮しない書庫)です。5ファイルで 3,061 バイトでした。できあがったフォルダです。
my-electron-app-linux-x64/
├── my-electron-app ← electron を改名した実行ファイル(234,483,016 バイト)
├── resources/
│ └── app.asar ← 自分のコード(3,061 バイト)
├── locales/ ← 言語ごとの .pak(55個)
├── chrome-sandbox chrome_crashpad_handler
├── icudtl.dat resources.pak snapshot_blob.bin v8_context_snapshot.bin
├── libffmpeg.so libvulkan.so.1 libvk_swiftshader.so
└── LICENSE LICENSES.chromium.html version
./my-electron-app を起動し、Chrome DevTools Protocol で開いているページを見た結果です。
page Hello from Electron renderer! file:///…/my-electron-app-linux-x64/resources/app.asar/index.html
Hello from Electron renderer!
This app is using Chrome (v156.0.8078.48), Node.js (v24.22.0), and Electron (v45.0.0)
ping → pong
ページは app.asar の中から読み込まれ、開発中と同じ表示と IPC の結果になりました。 公式によると、Windows は resources\app.asar、macOS は アプリ名.app/Contents/Resources/app.asar が同じ役割で、asar にせず resources/app フォルダに置く形も使えます。
Electron Forge と electron-builder
実際の配布では、インストーラーの作成・コード署名・公開までをまとめて行う道具を使います。
Electron Forge(8.0.1)
Electron の公式ドキュメントがすすめる道具
npx create-electron-app@latest でひな形
package → make → publish の3段階
Fuses のプラグインが全テンプレートに入っている
electron-builder(26.15.3)
package.json の build に設定を書く
NSIS・AppImage など出力の種類が多い
自動更新の electron-updater と組で使う
macOS の公証・Windows の署名に対応
Electron Forge で、既存のプロジェクトを取り込んでから配布物を作る手順です(公式チュートリアル Packaging Your Application)。
npx create-electron-app@latest import
npm run make
取り込むと、package.json の scripts が次の形になります。
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make"
}
npm run make は、まず electron-forge package でコードと Electron 本体を1つのフォルダ(out/アプリ名-OS-CPU/)にまとめ、次に設定した maker ごとに配布物を out/make/ に作ります。新しく作るなら npx create-electron-app@latest my-app --template=vite-typescript のようにテンプレートを選べます(webpack・webpack-typescript・vite・vite-typescript の4つ)。@electron-forge/cli 8.0.1 の engines は Node.js 22.13.0 以上です。
| 作りたいもの | Forge の maker(npm) | electron-builder の target |
|---|---|---|
| Windows のインストーラー | maker-squirrel・maker-wix・maker-msix |
nsis・msi・squirrel・appx |
| Windows の持ち運べる exe | ― | portable |
| macOS | maker-dmg・maker-pkg・maker-zip |
dmg・pkg・mas・zip |
| Linux | maker-deb・maker-rpm・maker-flatpak・maker-snap |
AppImage・deb・rpm・snap・pacman |
| zip などの書庫 | maker-zip |
zip・7z・tar.gz ほか |
electron-builder は、README の Quick Setup Guide のとおり package.json に設定と scripts を書きます。
{
"build": {
"appId": "jp.example.myapp",
"mac": { "category": "public.app-category.developer-tools" }
},
"scripts": {
"app:dir": "electron-builder --dir",
"app:dist": "electron-builder",
"postinstall": "electron-builder install-app-deps"
}
}
--dir はインストーラーを作らずにフォルダだけを作る指定で、中身を確かめるときに使います。install-app-deps は、ネイティブのモジュールを Electron の版に合わせてビルドし直すコマンドです。
コード署名
公式チュートリアルは、配布するアプリへのコード署名を強くすすめていて、自動更新には署名が欠かせないと書いています。macOS ではアプリ(.app)を作る段階で署名し、Windows では配布するインストーラーに署名します。electron-builder は macOS の公証(notarization)と Windows の Authenticode の署名に対応しています。
Fusesで使わない機能を切る(実物)
Fuses は、Electron の実行ファイルの中にある「機能のオン・オフのビット」です。 パッケージ化のときに切り替え、その後に署名すると、OS の署名の確認で元に戻せなくなります(公式の Electron Fuses のページ)。手元の実行ファイルを @electron/fuses で読んだ結果です。
$ npx @electron/fuses read --app ./my-electron-app
Analyzing app: my-electron-app
Fuse Version: v1
RunAsNode is Enabled
EnableCookieEncryption is Disabled
EnableNodeOptionsEnvironmentVariable is Enabled
EnableNodeCliInspectArguments is Enabled
EnableEmbeddedAsarIntegrityValidation is Disabled
OnlyLoadAppFromAsar is Disabled
LoadBrowserProcessSpecificV8Snapshot is Disabled
GrantFileProtocolExtraPrivileges is Enabled
WasmTrapHandlers is Enabled
RunAsNode が有効だと、環境変数 ELECTRON_RUN_AS_NODE=1 を付けたとき、アプリの実行ファイルがただの Node.js として動きました。
$ ELECTRON_RUN_AS_NODE=1 ./my-electron-app -e "console.log('node', process.versions.node, 'electron', process.versions.electron)"
node 24.22.0 electron 45.0.0
4つの Fuse を切り替えます。
$ npx @electron/fuses write --app ./my-electron-app RunAsNode=off EnableNodeOptionsEnvironmentVariable=off EnableNodeCliInspectArguments=off OnlyLoadAppFromAsar=on
RunAsNode is Enabled and will become Disabled
EnableNodeOptionsEnvironmentVariable is Enabled and will become Disabled
EnableNodeCliInspectArguments is Enabled and will become Disabled
OnlyLoadAppFromAsar is Disabled and will become Enabled
Writing to app: my-electron-app
Fuses written to disk
切り替えた後は、同じ ELECTRON_RUN_AS_NODE=1 を付けても Node.js としては動かず、ふつうにアプリの画面が起動しました。OnlyLoadAppFromAsar を有効にして app.asar を外し、代わりに resources/app フォルダを置くと、アプリは何も表示せずに終了コード1で終わりました。
| Fuse | 既定 | 切ると防げること |
|---|---|---|
RunAsNode |
有効 | アプリの実行ファイルを Node.js として使われること |
EnableNodeOptionsEnvironmentVariable |
有効 | NODE_OPTIONS でコードを差し込まれること |
EnableNodeCliInspectArguments |
有効 | --inspect でデバッガーをつながれること |
OnlyLoadAppFromAsar(有効にする) |
無効 | resources/app フォルダに置いたコードを読み込まれること |
EnableEmbeddedAsarIntegrityValidation(有効にする) |
無効 | app.asar の書き換え(macOS・Windows) |
GrantFileProtocolExtraPrivileges |
有効 | file:// のページに余分な権限を与えること |
RunAsNode を切ると、メインプロセスの child_process.fork が使えなくなります(公式)。使っているときは utilityProcess に置き換えます。
Electronアプリの自動更新(autoUpdater・update-electron-app・electron-updater)
この節では、配布したアプリを自動で新しい版にする方法の選び方が分かります。
| 方法 | 対応する OS・形式 | 必要なもの |
|---|---|---|
update-electron-app+update.electronjs.org |
macOS・Windows | 公開の GitHub リポジトリ、GitHub Releases、macOS は署名 |
update-electron-app+静的ストレージ(S3 等) |
macOS・Windows | Forge の ZIP・Squirrel.Windows の maker が出すメタデータ |
組み込みの autoUpdater+更新サーバー |
macOS(Squirrel.Mac)・Windows(Squirrel.Windows・MSIX) | Hazel・Nuts など、または自前のサーバー |
electron-updater(electron-builder) |
macOS の DMG・Windows の NSIS・Linux の AppImage | publish の設定(GitHub Releases・S3 など) |
Electron の組み込みの autoUpdater は Linux に対応していません。 公式の autoUpdater のページは「There is no built-in support for auto-updater on Linux」とし、ディストリビューションのパッケージ管理を使うよう書いています。macOS では、アプリに署名していないと自動更新できません。
update.electronjs.org(Electron チームの無料の更新サービス)を使う場合は、メインプロセスに次の2行を書きます(update-electron-app 3.3.0 の README)。起動時と、その後10分ごとに更新を確かめ、ダウンロードが済むと再起動を促すダイアログを出します。
const { updateElectronApp } = require('update-electron-app')
updateElectronApp()
electron-builder で作った配布物には、electron-updater を使います。公式の Auto Update のページは、専用の更新サーバーが要らないこと、macOS だけでなく Windows でも署名を確かめることを、組み込みの autoUpdater との違いに挙げています。
const { autoUpdater } = require('electron-updater')
autoUpdater.checkForUpdatesAndNotify()
ElectronをReact・Vite・TypeScriptと組み合わせる
この節では、画面を React などで作るときの構成が分かります。
Electron の画面はふつうの Web ページなので、React・Vue・Svelte などで作れます。 組み合わせ方は次の2つが多く使われています。
| 方法 | 始め方 | 特徴 |
|---|---|---|
| Electron Forge の Vite テンプレート | npx create-electron-app@latest my-app --template=vite-typescript |
配布まで Forge でそろう。React は後から入れる |
| electron-vite(6.0.0) | npm の electron-vite |
Vite を土台にした Electron 用のビルドの道具 |
どちらの場合も、開発中の画面は Vite の開発サーバー(http://localhost:…)から、配布物では file:// か独自のプロトコルから読み込みます。preload を何ファイルかに分ける場合は、サンドボックスのためバンドラーで1つにまとめます。Vite で React のプロジェクトを作る手順は、関連記事「React環境構築をViteで行う手順|create viteの使い方」で扱っています。
ElectronとTauriの違い
この節では、よく比べられる Tauri との違いが、各公式の情報と手元の実測で分かります。
| 比べる点 | Electron | Tauri |
|---|---|---|
| 画面を描くエンジン | 同梱の Chromium(45.0.0 は M156) | OS の WebView(WebView2・WKWebView・WebKitGTK) |
| 裏側の処理の言語 | JavaScript(Node.js 24.22.0) | Rust(Swift・Kotlin も) |
| 対応する OS | Windows・macOS・Linux | 左の3つ+iOS・Android(Tauri 2) |
| アプリの大きさ | Linux x64 の本体だけで 274MB(実測) | 最小で 600KB 未満にできる(公式) |
| 画面からの呼び出し | ipcRenderer.invoke/ipcMain.handle |
invoke/#[tauri::command] |
| 自動更新 | 組み込みの autoUpdater(macOS・Windows) |
公式の updater プラグイン(署名は必須) |
| ライセンス | MIT | Apache-2.0 または MIT |
| 最新版(npm) | electron 45.0.0 | @tauri-apps/cli 2.12.4 |
Electron は Chromium を同梱するので、どの OS でも同じエンジンで描きます。Tauri は OS の WebView を使うので、アプリは小さくなり、描くエンジンと版は OS によって変わります。 Tauri の公式の Webview Versions のページは、macOS・iOS の WKWebView は OS の更新で、Linux の WebKitGTK はディストリビューションのパッケージで版が決まると書いています。Tauri も「Core プロセス」と「WebView プロセス」に分かれる作りで、公式は Electron に似た作りだと説明しています。Rust の基本は、関連記事「Rust入門|所有権からCLI作成までコピペで動くコード付き」で扱っています。
| 状況 | 選びやすいもの |
|---|---|
| どの OS でも同じ見た目・同じ Web の機能で動かしたい | Electron |
| チームが JavaScript・Node.js だけで書きたい | Electron |
| npm のネイティブモジュールや Node.js のライブラリを多く使う | Electron |
| 配布物を小さくしたい、Rust で書ける | Tauri |
| 同じコードでスマホのアプリも作りたい | Tauri、または Flutter・React Native |
スマホのアプリも視野に入れる場合は、関連記事「Flutterとは|始め方・インストールとDartの基本を図と実例で解説」と「React Nativeとは|始め方・環境構築・Expoとの違いを実例で解説」で扱っています。
Electronのよくあるエラーと直し方
この節では、エラー文から原因と直し方を引けます。13件は手元でわざと起こした原文です。
| エラー文・症状 | 原因 | 直し方 |
|---|---|---|
ReferenceError: require is not defined |
画面の JS で require を使った |
preload の contextBridge+IPC に移す |
window.myApi が undefined |
preload で window に代入した |
contextBridge.exposeInMainWorld |
Unable to load preload script + ENOENT |
preload のパスが違う | path.join(__dirname, 'preload.js') |
preload script must have absolute path. |
preload を相対パスで書いた | 絶対パスにする |
Error: module not found: fs |
サンドボックスの preload で Node.js のモジュール | 処理をメインに移し IPC で呼ぶ |
No handler registered for '…' |
ipcMain.handle が無い・名前違い |
チャンネル名をそろえ、先に登録 |
Attempted to register a second handler for '…' |
同じ名前で2回 handle |
起動時に1回だけ登録 |
An object could not be cloned. |
関数や DOM を IPC で送った | 文字列・数値・配列などに変える |
Cannot create BrowserWindow before app is ready |
whenReady の前にウィンドウを作った |
app.whenReady().then(…) の中で |
Unable to find Electron app at … |
package.json が無い・main が違う |
main に入口のファイルを書く |
Running as root without --no-sandbox is not supported. |
root で起動した(コンテナ・CI など) | 一般ユーザーで起動する |
Electron Security Warning (Insecure Content-Security-Policy) |
CSP が無い | <meta http-equiv="Content-Security-Policy"> |
The NODE_OPTION --use-openssl-ca is not supported in Electron |
NODE_OPTIONS に Electron で使えない指定 |
その指定を外して起動する |
No handler registered(IPCの受け口が無い)
Error occurred in handler for 'missing': [Error: No handler registered for 'missing']
Error invoking remote method 'missing': Error: No handler registered for 'missing'
1行目がメインプロセスの出力、2行目がレンダラーに届いたエラーです。invoke と handle のチャンネル名のつづりと、handle を登録する前にページが呼んでいないかを確かめます。逆に、同じ名前で handle を2回登録すると Attempted to register a second handler for 'ping' の例外になりました。createWindow の中に handle を書くと、ウィンドウを作るたびに登録されて同じ形になるので、受け口は app.whenReady() の中で1回だけ登録します。
preloadが読み込まれない
Unable to load preload script: /…/preload-typo.js
Error: ENOENT: no such file or directory, open '/…/preload-typo.js'
preload が読み込まれなくても、ウィンドウはふつうに開きます。画面からは「関数が undefined」としか見えないので、レンダラーのコンソールかメインの webContents.on('preload-error', …) で原因を見ます。preload: 'preload.js' のように相対パスで書くと、ターミナルに preload script must have absolute path. と出て、同じく読み込まれませんでした。
rootで起動すると止まる
[1023/161522.674845:FATAL:electron/shell/app/electron_main_delegate.cc:224] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.
/…/node_modules/electron/dist/electron exited with signal SIGTRAP
Linux で root のまま起動すると、electron --version でもこの文で止まりました。Docker のコンテナや CI では root で動くことが多いので、一般ユーザーで起動します。--no-sandbox を付けると動きますが、公式の Process Sandboxing のページは、Chromium のサンドボックスをすべて外すこのフラグを試験の目的だけに使い、本番では使わないよう書いています。
Electronの本体の取得に失敗する
npm install の後の初回の起動で本体を取りに行くので、ネットワークの問題はこのときに出ます。electron 45.0.0 の index.js には、取得に失敗したときの次の文が書かれています。
Electron failed to install correctly. Please delete `node_modules/electron` and run "npx install-electron --no" manually.
公式のインストールのページは、取得の失敗はほとんどがネットワークの問題(ECONNRESET・ETIMEDOUT など)だとしています。手元でも1回目の取得が通信の途中のエラー(Node.js の AssertionError)で止まり、もう一度 install-electron を動かすと通りました。プロキシの内側では ELECTRON_GET_USE_PROXY、社内のミラーを使うときは ELECTRON_MIRROR を設定します。
よくある質問
Q. Electronとは簡単に言うと何ですか? A. HTML・CSS・JavaScript で、Windows・macOS・Linux のデスクトップアプリを作るフレームワークです。Chromium(画面)と Node.js(OS の機能)をアプリに同梱して動かします。
Q. Electronの読み方と意味は? A. 「エレクトロン」です。英語の electron(電子)と同じつづりのソフトウェアの名前で、2015年に「Atom Shell」から改名されました。
Q. Electronは無料ですか?商用利用できますか? A. MIT ライセンスで無料、商用のアプリにも使えます。配布物には Chromium などのライセンス表示のファイルが含まれます。
Q. Electronの最新バージョンは? A. 2026年10月23日時点の npm の最新は 45.0.0(Chromium 156・Node.js 24.22.0)です。サポートされるのは最新の安定版3つ(45・44・43)で、42 は2026年10月20日にサポートが終わりました。
Q. Electronはオワコンですか? A. 2026年10月時点でも約8週間ごとに新しいメジャー版が出ていて、公式サイトには VS Code・Slack・Discord・Notion・Figma などの利用例が並んでいます。配布物の大きさを重く見る場合は Tauri なども選ばれています(違いの節)。
Q. Electronのアプリが重いのはなぜですか? A. Chromium と Node.js をアプリごとに同梱し、Chromium と同じく複数のプロセスで動くためです。手元の最小のアプリでも本体が 274MB(Linux x64、展開後)、ウィンドウ1枚で4つのプロセスが動きました。
Q. ElectronでReactやVueは使えますか? A. 使えます。画面はふつうの Web ページなので、Electron Forge の Vite テンプレートや electron-vite で React・Vue のプロジェクトを組めます。
Q. Electronでexeを作るには?
A. Electron Forge(npm run make)か electron-builder(npm run app:dist)を使います。Forge なら Squirrel.Windows・WiX・MSIX、electron-builder なら NSIS・MSI・portable などの形で作れます(パッケージ化の節)。
Q. preloadとcontextBridgeは何のためにありますか?
A. 画面のページに Node.js を渡さずに、必要な機能だけを関数として公開するためです。preload はページより先に動き、contextBridge.exposeInMainWorld で公開した関数だけがページから見えます。
Q. ElectronでiOSやAndroidのアプリは作れますか? A. 作れません。Electron の対象は Windows・macOS・Linux のデスクトップです。スマホも同じコードで作るなら、Tauri 2・Flutter・React Native などが候補になります。
Q. ElectronとTauriはどちらがよいですか? A. どの OS でも同じ Chromium で動かしたい、JavaScript だけで書きたいなら Electron、配布物を小さくしたい・Rust で書けるなら Tauri が選ばれやすいです。比較は違いの節の表のとおりです。
まとめ
- Electron は、Chromium と Node.js を同梱して HTML・CSS・JavaScript でデスクトップアプリを作るフレームワーク。MIT で無料。読み方はエレクトロン。
- 作りはメインプロセス(Node.js・OS の機能)とレンダラー(画面)。2つは preload の
contextBridgeと IPC(invoke/handle)でつなぐ。 npm installで入るのは 14MB。本体(Linux x64 で 274MB)は 42.0 から初回の起動で取得される。最新は 45.0.0(Chromium 156・Node.js 24.22.0)。- 既定の
nodeIntegration: false・contextIsolation: true・sandbox: trueのままにし、用事ごとの関数だけを公開する。メインで送り元と引数を確かめる。 - パッケージ化の正体は「本体のフォルダ+
resources/app.asar+実行ファイルの改名」。実際の配布は Electron Forge か electron-builder で、署名する。 - Fuses で
RunAsNodeなどを切ると、アプリの実行ファイルを Node.js として使われなくなった。 - 自動更新は update-electron-app か electron-updater。組み込みの
autoUpdaterは Linux に対応していない。 - Tauri は OS の WebView と Rust で小さく作れ、Electron はどの OS でも同じ Chromium で動く。
参考・出典
確認日はいずれも 2026年10月23日です。
- Electron(公式サイト):https://www.electronjs.org/
- Electron「Building your First App」:https://www.electronjs.org/docs/latest/tutorial/tutorial-first-app
- Electron「Using Preload Scripts」:https://www.electronjs.org/docs/latest/tutorial/tutorial-preload
- Electron「Process Model」:https://www.electronjs.org/docs/latest/tutorial/process-model
- Electron「Inter-Process Communication」:https://www.electronjs.org/docs/latest/tutorial/ipc
- Electron「Context Isolation」:https://www.electronjs.org/docs/latest/tutorial/context-isolation
- Electron「Process Sandboxing」:https://www.electronjs.org/docs/latest/tutorial/sandbox
- Electron「Security」:https://www.electronjs.org/docs/latest/tutorial/security
- Electron「Electron Fuses」:https://www.electronjs.org/docs/latest/tutorial/fuses
- Electron「Advanced Installation Instructions」:https://www.electronjs.org/docs/latest/tutorial/installation
- Electron「Application Packaging / Distribution」:https://www.electronjs.org/docs/latest/tutorial/application-distribution
- Electron「Packaging Your Application」:https://www.electronjs.org/docs/latest/tutorial/tutorial-packaging
- Electron「Updating Applications」:https://www.electronjs.org/docs/latest/tutorial/updates
- Electron「autoUpdater」:https://www.electronjs.org/docs/latest/api/auto-updater
- Electron「Electron Releases」:https://www.electronjs.org/docs/latest/tutorial/electron-timelines
- Electron「Breaking Changes」:https://www.electronjs.org/docs/latest/breaking-changes
- Electron Releases「Schedule」:https://releases.electronjs.org/schedule
- Electron Blog「Electron」(2015年4月23日):https://www.electronjs.org/blog/electron
- Electron Forge:https://www.electronforge.io/
- electron-builder:https://www.electron.build/
- electron-builder「Auto Update」:https://www.electron.build/auto-update.html
- electron-builder(GitHub README):https://github.com/electron-userland/electron-builder
- npm「electron」:https://www.npmjs.com/package/electron
- npm「update-electron-app」:https://www.npmjs.com/package/update-electron-app
- Tauri「What is Tauri?」:https://v2.tauri.app/start/
- Tauri「Process Model」:https://v2.tauri.app/concept/process-model/
- Tauri「Webview Versions」:https://v2.tauri.app/reference/webview-versions/
- Tauri「Calling Rust from the Frontend」:https://v2.tauri.app/develop/calling-rust/
- Tauri「Updater」:https://v2.tauri.app/plugin/updater/
- Tauri Blog「Tauri 2.0 Stable Release」:https://v2.tauri.app/blog/tauri-20/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Electronとは|使い方・仕組み・安全なIPC・パッケージ化を実例で解説」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。