メインコンテンツへスキップ

クイックスタート

このガイドでは、electron/electron-quick-startに似た、Electronでの最小限のHello Worldアプリを作成する手順を説明します。

このチュートリアルの終わりまでに、アプリは、実行されているChromium、Node.js、およびElectronのバージョンに関する情報を表示するウェブページを表示するブラウザウィンドウを開きます。

前提条件

Electronを使用するには、Node.jsをインストールする必要があります。利用可能な最新のLTSバージョンを使用することをお勧めします。

お使いのプラットフォーム用のプリビルドインストーラーを使用してNode.jsをインストールしてください。それ以外の場合、異なる開発ツールとの間に非互換性の問題が発生する可能性があります。

Node.jsが正しくインストールされたことを確認するには、ターミナルクライアントで次のコマンドを入力します。

node -v
npm -v

コマンドは、Node.jsとnpmのバージョンをそれぞれ出力する必要があります。

注: ElectronはNode.jsをバイナリに埋め込んでいるため、コードを実行するNode.jsのバージョンはシステムで実行されているバージョンとは関係ありません。

アプリケーションを作成する

プロジェクトの足場を作る

Electronアプリは、他のNode.jsプロジェクトと同じ一般的な構造に従います。最初に、フォルダーを作成し、npmパッケージを初期化します。

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

インタラクティブなinitコマンドは、構成でいくつかのフィールドを設定するように求めます。このチュートリアルでは、従うべきいくつかのルールがあります。

  • entry pointmain.jsである必要があります。
  • authordescriptionは任意の値にすることができますが、アプリのパッケージングには必要です。

package.jsonファイルは次のようになります。

{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}

次に、electronパッケージをアプリのdevDependenciesにインストールします。

npm install --save-dev electron

注: Electronのインストールで問題が発生した場合は、高度なインストールガイドを参照してください。

最後に、Electronを実行できるようにする必要があります。scriptspackage.json構成のフィールドに、次のようにstartコマンドを追加します。

{
"scripts": {
"start": "electron ."
}
}

このstartコマンドを使用すると、開発モードでアプリを開くことができます。

npm start

注: このスクリプトは、プロジェクトのルートフォルダーでElectronを実行するように指示します。この段階では、アプリはすぐに、実行するアプリが見つからないというエラーをスローします。

メインプロセスを実行する

すべてのElectronアプリケーションのエントリポイントは、そのmainスクリプトです。このスクリプトは、完全なNode.js環境で実行され、アプリのライフサイクルを制御し、ネイティブインターフェイスを表示し、特権付き操作を実行し、レンダラープロセスを管理する(詳細については後述)メインプロセスを制御します。

実行中、Electronはアプリのpackage.json構成のmainフィールドでこのスクリプトを探します。これは、アプリの足場ステップで構成したはずです。

mainスクリプトを初期化するには、プロジェクトのルートフォルダーにmain.jsという名前の空のファイルを作成します。

注: この時点でstartスクリプトを再度実行すると、アプリはエラーをスローしなくなります!ただし、main.jsにコードを追加していないため、まだ何も実行されません。

Webページを作成する

アプリケーションのウィンドウを作成する前に、ウィンドウにロードされるコンテンツを作成する必要があります。Electronでは、各ウィンドウは、ローカルHTMLファイルまたはリモートURLからロードできるWebコンテンツを表示します。

このチュートリアルでは、前者を行います。プロジェクトのルートフォルダーにindex.htmlファイルを作成します。

<!DOCTYPE html>
<html lang="en">
<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'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
</body>
</html>

注: このHTMLドキュメントを見ると、バージョン番号が本文テキストに欠落していることがわかります。後でJavaScriptを使用して手動で挿入します。

ブラウザウィンドウでWebページを開く

Webページができたので、アプリケーションウィンドウにロードします。これを行うには、次の2つのElectronモジュールが必要です。

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

メインプロセスはNode.jsを実行するため、main.jsファイルの先頭でこれらをCommonJSモジュールとしてインポートできます。

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

次に、index.htmlを新しいBrowserWindowインスタンスにロードするcreateWindow()関数を追加します。

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

win.loadFile('index.html')
}

次に、このcreateWindow()関数を呼び出してウィンドウを開きます。

Electronでは、ブラウザウィンドウはappモジュールのreadyイベントが発生した後にのみ作成できます。app.whenReady()APIを使用すると、このイベントを待機できます。whenReady()がPromiseを解決した後、createWindow()を呼び出します。

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

注: この時点で、ElectronアプリケーションはWebページを表示するウィンドウを正常に開くはずです!

ウィンドウのライフサイクルを管理する

ブラウザウィンドウを開くことができるようになりましたが、各プラットフォームに対してよりネイティブな感じにするには、いくつかの追加のボイラープレートコードが必要です。アプリケーションウィンドウはOSごとに動作が異なり、Electronはこれらの規約をアプリに実装する責任を開発者に課します。

一般に、processグローバルのplatform属性を使用して、特定のオペレーティングシステム用に特定のコードを実行できます。

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

WindowsとLinuxでは、すべてのウィンドウを終了すると、一般的にアプリケーション全体が終了します。

これを実装するには、appモジュールの'window-all-closed'イベントをリッスンし、ユーザーがmacOS(darwin)を使用していない場合はapp.quit()を呼び出します。

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

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

LinuxおよびWindowsアプリはウィンドウが開いていないと終了しますが、macOSアプリは通常、ウィンドウが開いていなくても実行を続け、ウィンドウが利用できないときにアプリをアクティブにすると、新しいウィンドウが開く必要があります。

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

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

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

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

注: この時点で、ウィンドウコントロールは完全に機能しているはずです!

プリロードスクリプトを使用してレンダラーからNode.jsにアクセスする

さて、最後に行うことは、Electronとその依存関係のバージョン番号をWebページに出力することです。

この情報へのアクセスは、Nodeのグローバルprocessオブジェクトを介してメインプロセスで行うのは簡単です。ただし、メインプロセスにはレンダラーのdocumentコンテキストへのアクセス権がないため、メインプロセスからDOMを編集することはできません。それらは完全に異なるプロセスにあります!

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

ここで、レンダラーにプリロードスクリプトをアタッチすると便利です。プリロードスクリプトは、レンダラープロセスがロードされる前に実行され、レンダラーグローバル(windowdocumentなど)とNode.js環境の両方にアクセスできます。

次のように、preload.jsという名前の新しいスクリプトを作成します。

window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}

for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})

上記のコードは、Node.jsのprocess.versionsオブジェクトにアクセスし、基本的なreplaceTextヘルパー関数を実行して、バージョン番号をHTMLドキュメントに挿入します。

このスクリプトをレンダラープロセスにアタッチするには、既存のBrowserWindowコンストラクターのwebPreferences.preloadオプションにプリロードスクリプトへのパスを渡します。

const { app, BrowserWindow } = require('electron')
// include the Node.js 'path' module at the top of your file
const path = require('node:path')

// modify your existing createWindow() function
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

win.loadFile('index.html')
}
// ...

ここでは、使用されている2つのNode.jsの概念があります。

  • __dirname文字列は、現在実行中のスクリプトのパス(この場合は、プロジェクトのルートフォルダー)を指します。
  • path.joinAPIは、複数のパスセグメントを結合して、すべてのプラットフォームで機能する結合されたパス文字列を作成します。

相対パスが開発モードとパッケージモードの両方で機能するように、現在実行中のJavaScriptファイルからの相対パスを使用します。

ボーナス:ウェブコンテンツに機能を追加する

この時点で、アプリケーションにさらに機能を追加する方法を知りたいかもしれません。

ウェブコンテンツとのインタラクションについては、レンダラープロセスにスクリプトを追加する必要があります。レンダラーは通常のウェブ環境で実行されるため、index.htmlファイルの閉じタグ</body>の直前に<script>タグを追加して、必要な任意のスクリプトを含めることができます。

<script src="./renderer.js"></script>

renderer.jsに含まれるコードは、webpackを使用してコードをバンドルおよびminifyしたり、Reactを使用してユーザーインターフェースを管理したりするなど、一般的なフロントエンド開発で使用するのと同じJavaScript APIとツールを使用できます。

まとめ

上記の手順に従うと、次のような完全に機能するElectronアプリケーションが完成するはずです。

Simplest Electron app

完全なコードは以下で入手できます。

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('node:path')

const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

// and load the index.html of the app.
mainWindow.loadFile('index.html')

// Open the DevTools.
// mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// preload.js

// All the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}

for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<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'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.

<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
const { app, BrowserWindow } = require('electron/main')
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(() => {
createWindow()

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

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

これまでの手順をまとめると、

  • Node.jsアプリケーションをブートストラップし、Electronを依存関係として追加しました。
  • アプリを制御し、Node.js環境で実行されるメインプロセスを実行するmain.jsスクリプトを作成しました。このスクリプトでは、ElectronのappモジュールとBrowserWindowモジュールを使用して、別のプロセス(レンダラー)でWebコンテンツを表示するブラウザウィンドウを作成しました。
  • レンダラーで特定のNode.js機能にアクセスするために、BrowserWindowコンストラクターにプリロードスクリプトをアタッチしました。

アプリケーションのパッケージ化と配布

新しく作成したアプリを配布する最も速い方法は、Electron Forgeを使用することです。

情報

Linux用のRPMパッケージをビルドするには、必要なシステム依存関係をインストールする必要があります。

  1. package.jsonファイルに説明を追加してください。そうしないと、rpmbuildが失敗します。空白の説明は無効です。

  2. Electron Forgeをアプリの開発依存関係として追加し、そのimportコマンドを使用してForgeのスキャフォールディングを設定します。

    npm install --save-dev @electron-forge/cli
    npx electron-forge import

    ✔ Checking your system
    ✔ Initializing Git Repository
    ✔ Writing modified package.json file
    ✔ Installing dependencies
    ✔ Writing modified package.json file
    ✔ Fixing .gitignore

    We have ATTEMPTED to convert your app to be in a format that electron-forge understands.

    Thanks for using "electron-forge"!!!
  3. Forgeのmakeコマンドを使用して配布可能ファイルを作成します。

    npm run make

    > my-electron-app@1.0.0 make /my-electron-app
    > electron-forge make

    ✔ Checking your system
    ✔ Resolving Forge Config
    We need to package your application before we can make it
    ✔ Preparing to Package Application for arch: x64
    ✔ Preparing native dependencies
    ✔ Packaging Application
    Making for the following targets: zip
    ✔ Making for target: zip - On platform: darwin - For arch: x64

    Electron Forgeは、パッケージが配置されるoutフォルダーを作成します。

    // Example for macOS
    out/
    ├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
    ├── ...
    └── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app