メインコンテンツへ飛ぶ

初めてのアプリのビルド

学習目標

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

プロジェクトのセットアップ

WSL の忌避

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

npm プロジェクトの初期化

Electron アプリは npm を利用して組み上げられ、package.json ファイルをエントリポイントとします。 まずフォルダを作成し、その中で npm init を実行して npm パッケージを初期化します。

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

このコマンドは、package.json のいくつかのフィールドに対する設定を確認します。 このチュートリアルの目的上、以下のルールに従ってください。

  • エントリポイントmain.js にしてください (後でそのファイルを作成します)。
  • author, license, and description can be any value, but will be necessary for packaging later on.

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

なぜ 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 のインストール手順

If installing Electron directly fails, please refer to our Advanced Installation documentation for instructions on download mirrors, proxies, and troubleshooting steps.

.gitignore の追加

.gitignore ファイルでは、Git での追跡を避けるファイルやディレクトリを指定します。 GitHub の Node.js gitignore テンプレート をコピーしてプロジェクトのルートフォルダに配置しておけば、プロジェクトの node_modules フォルダのコミットを回避できます。

Electron アプリの実行

関連項目

Read Electron's process model documentation to better understand how Electron's multiple processes work together.

どのような Electron アプリケーションのエントリポイントも、package.json で定義した main スクリプトになります。 このスクリプトは メインプロセス を制御します。メインプロセスは Node.js 環境で動作し、アプリのライフサイクル制御、ネイティブインターフェースの表示、特権操作、レンダラープロセス (後述) の管理を担います。

最初の Electron アプリを作成する前に、まず小さなスクリプトを使用して、メインプロセスのエントリポイントが正しく設定されていることを確認します。 プロジェクトのルートフォルダに main.js というファイルを作成し、以下の 1 行を記述します。

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

Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code with the electron command (you can even use it as a REPL). このスクリプトを実行するには、package.json のscripts フィールド内に start コマンドとして electron . を追加します。 このコマンドは、Electron の実行形式に対して、カレントディレクトリにある main スクリプトを探して開発モードで実行するように指示します。

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 で初めてコードを 1 行実行しました! 次に、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>

Now that you have a web page, you can load it into an 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 (Line 1)
const { app, BrowserWindow } = require('electron')

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

  • app, which controls your application's event lifecycle.
  • BrowserWindow, which creates and manages app windows.
モジュールの大文字小文字規約

app モジュールと BrowserWindow モジュールの大文字小文字の規則の違いにお気づきでしょうか。 ここでは Electron は典型的な JavaScript の慣習に従っています。PascalCase のモジュールはインスタンス化可能なクラスコンストラクタ (例: BrowserWindow、Tray、Notification) であるのに対し、camelCase のモジュールはインスタンス化できません (例: app、ipcRenderer、webContents)。

型付きの import エイリアス

TypeScript コードを記述する際の型検査を改善するために、electron/main からメインプロセスのモジュールをインポートする選択ができます。

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

For more information, see the Process Model docs.

Electron での ES Modules

Electron 28 から、Electron での ECMAScript Modules (例えば import によるモジュールの読み込み) がサポートされています。 Electron での ESM の状態についてさらなる情報は、私たちの ESM のガイド にあります。

ウインドウを作成する再使用可能な関数を書く

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

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

win.loadFile('index.html')
}

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

main.js (Lines 12-14)
app.whenReady().then(() => {
createWindow()
})

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

In Electron, BrowserWindows can only be created after the app module's ready event is fired. You can wait for this event by using the app.whenReady() API and calling createWindow() once its promise is fulfilled.

info

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

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

しかし, Electron は ready イベントのヘルパーとして app.whenReady() を公開しています。これは直接リッスンすることによる些細なミスを回避するためのものです。 詳細は electron/electron#21972 をご参照ください。

この時点で、Electron アプリケーションの start コマンドを実行すると、ウェブページを表示するウインドウが正常に開くでしょう。

アプリがウインドウに表示する各ウェブページは、レンダラー プロセスという (または単に レンダラー と略す) 個別のプロセスで実行されます。 レンダラープロセスは典型的なフロントエンドのウェブ開発と同じように JavaScript の API へアクセスでき、同じツール、例えば webpack によるコードのバンドルと Minify、React によるユーザーインターフェイスの構築などが利用できます。

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

アプリケーションウインドウは、オペレーティングシステムによって動作が異なります。 Electron はそれぞれの慣習をデフォルトでは強制せず、慣習に従いたい場合はアプリのコードで実装する選択肢を提供します。 app モジュールと BrowserWindow モジュールが発生するイベントをリッスンすることで、基本的なウインドウの慣習的動作を実装できます。

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

Node の process.platform 変数を確認することで、特定プラットフォームの条件下でコードを実行できます。 注意として、取りうるプラットフォームの値は Electron が実行できる win32 (Windows)、linux (Linux)、darwin (macOS) の 3 つのみです。

全ウインドウを閉じた時にアプリを終了する (Windows & Linux)

一般的に Windows や Linux では、すべてのウインドウを閉じるとアプリケーションが完全に終了します。 To implement this pattern in your Electron app, listen for the app module's window-all-closed event, and call app.quit() to exit your app if the user is not on macOS.

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

開いたウインドウがない場合にウインドウを開く (macOS)

一方、macOS アプリは一般的に、ウインドウを開いていなくても動作し続けます。 ウインドウがないときにアプリをアクティブにすると、新規ウインドウが開かれるでしょう。

To implement this feature, listen for the app module's activate event, and call your existing createWindow() method if no BrowserWindows are open.

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"
}
]
}

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

この launch.json ファイルでは、以下 3 つの構成を作成しています。

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

Renderer でプロセスにアタッチしているため、コードの最初の行が実行される前にデバッガーが接続しようとすると、早すぎてスキップされることがあります。 これは開発モードでコードを実行する前に、ページを更新したりタイムアウトを設定することで回避できます。

関連項目

デバッグ分野をより深く掘り下げたい場合は、以下のガイドに詳しい情報が掲載されています。

概要

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

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

レンダラープロセス (または略してレンダラー) はグラフィカルなコンテンツの表示を担います。 レンダラーにウェブページを読み込むには、ウェブアドレスまたはローカルの HTML ファイルを指定します。 レンダラーの動作は通常のウェブページと非常に似ており、同じウェブの API にアクセスできます。

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