クイックスタート
このガイドでは、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パッケージを初期化します。
- npm
- Yarn
mkdir my-electron-app && cd my-electron-app
npm init
mkdir my-electron-app && cd my-electron-app
yarn init
インタラクティブなinit
コマンドは、構成でいくつかのフィールドを設定するように求めます。このチュートリアルでは、従うべきいくつかのルールがあります。
entry point
はmain.js
である必要があります。author
とdescription
は任意の値にすることができますが、アプリのパッケージングには必要です。
package.json
ファイルは次のようになります。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}
次に、electron
パッケージをアプリのdevDependencies
にインストールします。
- npm
- Yarn
npm install --save-dev electron
yarn add --dev electron
注: Electronのインストールで問題が発生した場合は、高度なインストールガイドを参照してください。
最後に、Electronを実行できるようにする必要があります。scripts
package.json
構成のフィールドに、次のようにstart
コマンドを追加します。
{
"scripts": {
"start": "electron ."
}
}
このstart
コマンドを使用すると、開発モードでアプリを開くことができます。
- npm
- Yarn
npm start
yarn 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プロセスの詳細については、プロセスモデルドキュメントを参照してください。
ここで、レンダラーにプリロードスクリプトをアタッチすると便利です。プリロードスクリプトは、レンダラープロセスがロードされる前に実行され、レンダラーグローバル(window
やdocument
など)と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.join
APIは、複数のパスセグメントを結合して、すべてのプラットフォームで機能する結合されたパス文字列を作成します。
相対パスが開発モードとパッケージモードの両方で機能するように、現在実行中のJavaScriptファイルからの相対パスを使用します。
ボーナス:ウェブコンテンツに機能を追加する
この時点で、アプリケーションにさらに機能を追加する方法を知りたいかもしれません。
ウェブコンテンツとのインタラクションについては、レンダラープロセスにスクリプトを追加する必要があります。レンダラーは通常のウェブ環境で実行されるため、index.html
ファイルの閉じタグ</body>
の直前に<script>
タグを追加して、必要な任意のスクリプトを含めることができます。
<script src="./renderer.js"></script>
renderer.js
に含まれるコードは、webpack
を使用してコードをバンドルおよびminifyしたり、Reactを使用してユーザーインターフェースを管理したりするなど、一般的なフロントエンド開発で使用するのと同じJavaScript APIとツールを使用できます。
まとめ
上記の手順に従うと、次のような完全に機能するElectronアプリケーションが完成するはずです。
完全なコードは以下で入手できます。
// 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>
- main.js
- preload.js
- index.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()
}
})
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
<p>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
</p>
</body>
</html>
これまでの手順をまとめると、
- Node.jsアプリケーションをブートストラップし、Electronを依存関係として追加しました。
- アプリを制御し、Node.js環境で実行されるメインプロセスを実行する
main.js
スクリプトを作成しました。このスクリプトでは、Electronのapp
モジュールとBrowserWindow
モジュールを使用して、別のプロセス(レンダラー)でWebコンテンツを表示するブラウザウィンドウを作成しました。 - レンダラーで特定のNode.js機能にアクセスするために、
BrowserWindow
コンストラクターにプリロードスクリプトをアタッチしました。
アプリケーションのパッケージ化と配布
新しく作成したアプリを配布する最も速い方法は、Electron Forgeを使用することです。
Linux用のRPMパッケージをビルドするには、必要なシステム依存関係をインストールする必要があります。
-
package.json
ファイルに説明を追加してください。そうしないと、rpmbuildが失敗します。空白の説明は無効です。 -
Electron Forgeをアプリの開発依存関係として追加し、その
import
コマンドを使用してForgeのスキャフォールディングを設定します。- npm
- Yarn
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"!!!yarn add --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"!!! -
Forgeの
make
コマンドを使用して配布可能ファイルを作成します。- npm
- Yarn
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: x64yarn 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: x64Electron 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