本文へスキップ

初めてのアプリ作成

チュートリアルに従ってください

学習目標

このチュートリアルのパートでは、Electron プロジェクトの設定方法と、最小限のスターターアプリケーションを作成する方法を学習します。このセクションの最後までに、ターミナルから開発モードで動作する Electron アプリを実行できるようになります。

プロジェクトの設定

WSL を避けてください

Windows マシンを使用している場合は、このチュートリアルに従う際に Windows Subsystem for Linux (WSL) を使用しないでください。アプリケーションを実行しようとすると問題が発生します。

npm プロジェクトの初期化

Electron アプリは、`npm init` を使用して `package.json` ファイルをエントリポイントとして npm でスキャフォールディングされます。フォルダーを作成し、その中に `npm init` を使用して npm パッケージを初期化することから始めます。

mkdir my-electron-app && cd my-electron-app
npm init

このコマンドを実行すると、`package.json` のいくつかのフィールドを構成するように求められます。このチュートリアルの目的では、いくつかのルールに従う必要があります。

  • エントリポイントは `main.js` である必要があります(このファイルはすぐに作成します)。
  • 作成者ライセンス、および説明には任意の値を使用できますが、後でパッケージ化するために必要になります。

次に、アプリの**devDependencies**に Electron をインストールします。これは、本番環境では必要ない、開発専用の外部パッケージ依存関係のリストです。

なぜ Electron は devDependency なのですか?

本番コードが Electron API を実行しているため、これは直感に反するように思えるかもしれません。ただし、パッケージ化されたアプリには Electron バイナリがバンドルされるため、本番環境の依存関係として指定する必要がなくなります。

npm install electron --save-dev

パッケージを初期化して Electron をインストールした後、`package.json` ファイルは次のようになります。また、Electron 実行可能ファイルを含む `node_modules` フォルダーと、インストールする正確な依存関係のバージョンを指定する `package-lock.json` ロックファイルも作成されます。

package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
高度な Electron インストール手順

Electron の直接インストールが失敗した場合は、ダウンロードミラー、プロキシ、およびトラブルシューティング手順に関する指示については、高度なインストールドキュメントを参照してください。

.gitignore の追加

.gitignoreファイルは、Git で追跡しないファイルとディレクトリを指定します。プロジェクトのルートフォルダーにGitHub の Node.js gitignore テンプレートのコピーを配置して、プロジェクトの `node_modules` フォルダーをコミットしないようにする必要があります。

Electron アプリの実行

さらに読む

Electron の複数プロセスがどのように連携して動作するかをより深く理解するには、Electron のプロセスモデルドキュメントをお読みください。

`package.json`で定義したmainスクリプトは、すべての Electron アプリケーションのエントリポイントです。このスクリプトは、**メインプロセス**を制御します。メインプロセスは Node.js 環境で実行され、アプリのライフサイクルの制御、ネイティブインターフェースの表示、特権操作の実行、およびレンダラープロセスの管理を担当します(詳細は後述)。

最初の Electron アプリを作成する前に、まず些細なスクリプトを使用して、メインプロセスのエントリポイントが正しく構成されていることを確認します。プロジェクトのルートフォルダーに、1行のコードを含む `main.js` ファイルを作成します。

main.js
console.log('Hello from Electron 👋')

Electron のメインプロセスは Node.js ランタイムであるため、`electron`コマンドを使用して任意の Node.js コードを実行できます(REPLとしても使用できます)。このスクリプトを実行するには、`package.json`のscriptsフィールドの`start`コマンドに`electron .`を追加します。このコマンドは、Electron 実行可能ファイルに現在のディレクトリにあるメインスクリプトを探して開発モードで実行するように指示します。

package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
npm run start

ターミナルには `Hello from Electron 👋` と表示されます。おめでとうございます。Electron で最初のコードを実行しました!次に、HTML を使用してユーザーインターフェースを作成し、それをネイティブウィンドウに読み込む方法を学習します。

ウェブページを BrowserWindow に読み込む

Electron では、各ウィンドウは、ローカル HTML ファイルまたはリモートウェブアドレスから読み込むことができるウェブページを表示します。この例では、ローカルファイルを読み込みます。プロジェクトのルートフォルダーに、基本的なウェブページを含む `index.html` ファイルを作成することから始めます。

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-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>👋</p>
</body>
</html>

これでウェブページができましたので、Electron BrowserWindow に読み込むことができます。`main.js` ファイルの内容を次のコードに置き換えます。各強調表示されたブロックについては、個別に説明します。

main.js
const { app, BrowserWindow } = require('electron')

const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()
})

モジュールのインポート

main.js (1行目)
const { app, BrowserWindow } = require('electron')

最初の行では、CommonJS モジュール構文を使用して 2 つの Electron モジュールをインポートしています。

  • app は、アプリケーションのイベントライフサイクルを制御します。
  • BrowserWindow は、アプリウィンドウを作成および管理します。
モジュールのキャピタライゼーション規則

**a**pp と **B**rowser**W**indow モジュールのキャピタライゼーションの違いに気付いたかもしれません。Electron はここで一般的な JavaScript の規則に従っており、PascalCase モジュールはインスタンス化可能なクラスコンストラクター(例:BrowserWindow、Tray、Notification)であるのに対し、camelCase モジュールはインスタンス化できません(例:app、ipcRenderer、webContents)。

型付きインポートエイリアス

TypeScript コードを記述する際の型チェックを向上させるために、`electron/main` からメインプロセスモジュールをインポートすることを選択できます。

const { app, BrowserWindow } = require('electron/main')

詳細については、プロセスモデルのドキュメントを参照してください。

Electron での ES モジュール

Electron 28 以降では、ECMAScript モジュール(つまり、`import` を使用してモジュールを読み込む)がサポートされています。Electron での ESM の状態と、アプリでそれらを使用する方法の詳細については、ESM ガイドを参照してください。

ウィンドウをインスタンス化する再利用可能な関数の記述

`createWindow()`関数は、ウェブページを新しい BrowserWindow インスタンスに読み込みます。

main.js (3~10行目)
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

win.loadFile('index.html')
}

アプリの準備ができたときに関数を呼び出す

main.js (12~14行目)
app.whenReady().then(() => {
createWindow()
})

Electron のコアモジュールの多くは、Node の非同期イベント駆動アーキテクチャに従う Node.js イベントエミッターです。app モジュールはこれらのエミッターの 1 つです。

Electron では、app モジュールのreadyイベントが発生した後にのみ、BrowserWindow を作成できます。app.whenReady() API を使用してこのイベントを待ち、プロミスが実行されたら `createWindow()` を呼び出すことができます。

情報

通常、エミッターの `.on` 関数を使用して Node.js イベントをリッスンします。

+ app.on('ready', () => {
- app.whenReady().then(() => {
createWindow()
})

しかし、Electron は ready イベントに対して直接リスンすることによる微妙な落とし穴を避けるために、app.whenReady() をヘルパーとして公開しています。詳細は electron/electron#21972 を参照してください。

この時点で、Electron アプリケーションの start コマンドを実行すると、ウェブページを表示するウィンドウが正常に開きます!

アプリがウィンドウに表示する各ウェブページは、レンダラープロセス(または簡単にレンダラー)と呼ばれる個別のプロセスで実行されます。レンダラープロセスは、コードをバンドルおよび縮小するための webpack の使用や、ユーザーインターフェースを構築するための React の使用など、通常のフロントエンドWeb開発で使用されるものと同じJavaScript APIとツールにアクセスできます。

アプリのウィンドウライフサイクルの管理

アプリケーションウィンドウは、オペレーティングシステムごとに動作が異なります。Electron は、これらの規則をデフォルトで強制するのではなく、希望する場合はアプリコードで実装する選択肢を提供します。アプリと BrowserWindow モジュールのイベントをリッスンすることで、基本的なウィンドウ規則を実装できます。

プロセス固有の制御フロー

Nodeの process.platform 変数を確認することで、特定のプラットフォームで条件付きでコードを実行できます。Electron が実行できるプラットフォームは、win32(Windows)、linux(Linux)、darwin(macOS)の3つだけです。

すべてのウィンドウが閉じられたときにアプリを終了する(Windows と Linux)

Windows と Linux では、すべてのウィンドウを閉じると、通常アプリケーション全体が終了します。このパターンを Electron アプリで実装するには、app モジュールの window-all-closed イベントをリッスンし、ユーザーが macOS を使用していない場合は、app.quit() を呼び出してアプリを終了します。

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

ウィンドウが開いていない場合にウィンドウを開く(macOS)

対照的に、macOS アプリは、ウィンドウが開いていなくても一般的に実行を続けます。ウィンドウがない状態でアプリをアクティブにすると、新しいウィンドウが開きます。

この機能を実装するには、app モジュールの activate イベントをリッスンし、BrowserWindow が開いていない場合は既存の createWindow() メソッドを呼び出します。

ready イベントの前にウィンドウを作成することはできないため、アプリが初期化された後でのみ activate イベントをリッスンする必要があります。これは、既存の whenReady() コールバック内で activate イベントをリッスンすることによって行います。

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

最終的なスターターコード

const { app, BrowserWindow } = require('electron/main')

const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})

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()
}
})

オプション:VS Codeからのデバッグ

VS Code を使用してアプリケーションをデバッグする場合は、メインプロセスとレンダラープロセスの両方に VS Code をアタッチする必要があります。実行するためのサンプル構成を次に示します。プロジェクト内の新しい .vscode フォルダーに `launch.json` 構成ファイルを作成します。

.vscode/launch.json
{
"version": "0.2.0",
"compounds": [
{
"name": "Main + renderer",
"configurations": ["Main", "Renderer"],
"stopAll": true
}
],
"configurations": [
{
"name": "Renderer",
"port": 9222,
"request": "attach",
"type": "chrome",
"webRoot": "${workspaceFolder}"
},
{
"name": "Main",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": [".", "--remote-debugging-port=9222"],
"outputCapture": "std",
"console": "integratedTerminal"
}
]
}

サイドバーから「実行とデバッグ」を選択すると、「メイン + レンダラー」オプションが表示され、メインプロセスとレンダラープロセスの両方でブレークポイントを設定したり、すべての変数を検査したりすることができます。

launch.json ファイルで行ったのは、3つの構成を作成することです。

  • Main はメインプロセスを開始し、リモートデバッグのためにポート 9222 を公開する(--remote-debugging-port=9222)ために使用されます。これは、Renderer のデバッガーをアタッチするために使用するポートです。メインプロセスは Node.js プロセスであるため、型は node に設定されています。
  • Renderer はレンダラープロセスをデバッグするために使用されます。メインプロセスがプロセスを作成するため、新しいプロセスを作成する代わりに、それに「アタッチ」する必要があります("request": "attach")。レンダラープロセスはWebプロセスであるため、使用するデバッガーは chrome です。
  • Main + renderer は、前のものを同時に実行する 複合タスク です。
注意

Renderer でプロセスにアタッチしているため、デバッガーが実行される前に接続するのに十分な時間がなかったため、コードの先頭行がスキップされる可能性があります。開発モードでコードを実行する前にページを更新するか、タイムアウトを設定することで、これを回避できます。

さらに読む

デバッグ領域をさらに深く掘り下げたい場合は、次のガイドで詳細情報を確認できます。

概要

Electron アプリケーションは npm パッケージを使用して設定されます。Electron 実行ファイルはプロジェクトの devDependencies にインストールする必要があり、package.json ファイル内のスクリプトを使用して開発モードで実行できます。

実行ファイルは、package.json の main プロパティにある JavaScript エントリポイントを実行します。このファイルは Electron のメインプロセスを制御し、Node.js のインスタンスを実行し、アプリのライフサイクル、ネイティブインターフェースの表示、特権操作の実行、およびレンダラープロセスの管理を担当します。

レンダラープロセス(または簡単にレンダラー)は、グラフィカルコンテンツの表示を担当します。WebアドレスまたはローカルHTMLファイルのいずれかを指定して、レンダラーにWebページをロードできます。レンダラーは通常のWebページと非常によく似ており、同じWeb APIにアクセスできます。

チュートリアルの次のセクションでは、特権APIを使用してレンダラープロセスを拡張する方法と、プロセス間で通信する方法について学習します。