Electronデスクトップアプリ開発入門(1)
Electronとは? アーキテクチャ/API/インストール方法/初期設定
Windows/macOS/Linuxで実行できるデスクトップアプリをWeb技術で作ろう! Electronの概要から開発を始めて動かすところまでを解説する。
Electronとは
Electronとは、Windows/macOS/Linuxで実行できるデスクトップアプリをHTML+CSS+JavaScriptといったWeb技術で開発できるフレームワークである。
「Web技術でできる」と書くと、制限が多いのではないか、さまざまなプラットフォームで実行するためには、ブラウザーハックのように面倒な記述が必要になるのではないかなど、ネガティブな印象を持つ人もいるだろうが、心配は不要だ。JavaScriptの実行エンジンはV8であるため、ES2015の新しい記法でJavaScriptを利用でき、さらにその上にNode.jsが組み込まれているため、npmで提供されている豊富で、かつファイルシステムやOSの機能を呼び出せる強力なライブラリを利用できる。レンダリングエンジンにはChromeのオープンソース実装であるChromiumが使われているため、さまざまなブラウザーに対応するためのベンダープレフィックスの記述は必要なく、Chromium上でだけ動くように記述すればよい。
Electronのルーツは、GitHubが開発したテキストエディターであるAtomの副産物として公開されたatom-shellにある。その強力な機能からAtomに限らずさまざまなアプリケーションのフレームワークとして利用され、Electronという名前に変更された。Electronで開発したアプリは、ブラウザー内で動作するわけではなく、ネイティブアプリケーションと同じように動作する。開発したアプリケーションは、各OSのネイティブのインストーラーとしてパッケージ化して配布できる。
Electronで開発されたアプリはもちろん全てではないものの、Electronのサイトで確認できる。Visual Studio CodeやSlackはだいたい想像が付くだろうが、ターミナルのHyperやパケットキャプチャーのDripCapのようにJavaScriptでそこまでできるのかと感心するようなものもある。
併せて参照してほしいリソース
Electronに必要な情報の多くはAwesome Electronにまとめられているので、開発を始める前にぜひ見てほしい。Awesome Electronには、以下のような見出しがある。
- Apps: Electronで開発されたアプリが列挙されていて、「Open Source」になっているものは、ソースの閲覧も可能だ。「Closed Source」のアプリでも、作り方の参考になることもあるだろう。
- Boilerplates: あらかじめライブラリが登録されたテンプレートが紹介されている。フロントのフレームワークとしてReactやVueを使いたい場合はこのテンプレートを使うとすぐに始められる。
- Tools: Electronの開発に役立つリソースが紹介されている。
- For Electron: Electronで開発するのに便利なモジュールが紹介されている。Electronの開発は、他のNode.jsの開発と同じで、既存のモジュールを組み合わせて使うことで開発効率を上げることができる。例えば、開発環境で実行されているかどうかを判別する「electron-is-dev」のような簡単なものが提供されていることからも、多数のモジュールがあって、知っていることで開発を効率化できることが予想できるだろう。
その他にもElectronの開発に役立つドキュメントや記事、ビデオなど多くのリソースにリンクされている。中でも日本語のリソースとして、日本語のSlackへのリンクと翻訳されたドキュメントへのリンクもある。ただし、翻訳されたドキュメントには一部、古い情報や翻訳されていないものも含まれるため、必要に応じて英語の原文も確認してほしい。
バージョン番号
Electronは、執筆時点の最新バージョンは1.4.14だが、頻繁にバージョンアップされている。多くの場合はバグフィックスだが、新しいAPIが追加されていることもある。
Electronのバージョン番号はセマンティックバージョニングが採用されており、APIに大きな変更がない場合は、マイナーバージョンアップとなる。
ただし、ElectronはNode.jsとChromiumを利用するフレームワークのため、それらのバージョン変更にも大きく影響される。ChromeのメジャーバージョンアップとNode.jsのマイナーバージョンアップがあった場合には、Electronはマイナーバージョンアップされる(例えば1.0.0から1.1.0になる)。
またElectron自身の重要な変更時にもマイナーバージョンアップされる。小さなバグ修正の場合は、パッチ・バージョンがアップされる(例えば1.0.0から1.0.1)。
Chromiumがメジャーバージョンアップされた場合、安定バージョンのChromiumのリリース後、1~2週後にアップデートされる。また、Node.jsがバージョンアップされた場合、安定するまで1カ月程度待ったところで、Electronもバージョンアップされる。
Electronをインストールする
node.js(npm)はあらかじめインストールされている環境を前提とする。インストールされていない場合は、node.jsのダウンロードページからパッケージをダウンロードしてインストールする。
Electronがインストールされていない場合は、npm
コマンドでインストールする(リスト1)。
npm install electron -g
|
npm
コマンドに-g
オプションを付けることで、グローバルインストールされるため、今後のインストールは不要になる。
アプリの初期設定とウィンドウの表示
最初のアプリを作成してみよう。
まずはアプリのフォルダーを作成する(リスト2)。
mkdir myapp01
cd myapp01
|
次にアプリの初期設定をするために、npm init
コマンドを実行する。リスト3に示すように、npm init
を実行すると、対話によって初期設定が行える。
$ npm init
name: (myapp01) ↙️
version: (1.0.0) ↙️
description: はじめてのElectronアプリです。↙️
entry point: (index.js) ↙️
test command: ↙️
git repository: ↙️
keywords: ↙️
author: 尾崎義尚↙️
license: (ISC) ↙️
|
括弧内に表示されているデフォルト値のままでよい場合は、Enterキーを押すだけでよい。
この上記の対話によって、リスト4の内容のpackage.jsonファイルが作成される。ここで細かく設定しなくても後からpackage.jsonファイルの記述を変更すればよいだけなので、最初は全てEnterキーだけでデフォルト値で作成してもよいだろう(なお、npm init -y
コマンドを実行すれば、全てEnterキーを押した場合のpackage.jsonファイルが作られる)。
{
"name": "myapp01",
"version": "1.0.0",
"description": "はじめてのElectronアプリです。",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "尾崎義尚",
"license": "ISC"
}
|
エントリーポイント(package.jsonファイルの記述ではmain
)として指定されたindex.jsファイルは自動では作成されないので、手動で作成する。ウィンドウを表示するために、index.jsファイルにリスト5のコードを記述していく。
const {app, BrowserWindow} = require('electron')
var mainWindows = null
app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadURL(`file://${__dirname}/index.html`)
mainWindow.on('closed', () => {
mainWindow = null
})
})
|
波かっこで代入する記述は、分割代入と呼ばれ、右辺のオブジェクトからプロパティ値を代入する記述方法である。以下の記述も同様の意味となり、Electronのサンプルコードは混在していることがあるため、両方を覚えておくとよい。本稿でも混在して記述している。
const app = require('electron').app
const BrowserWindow = require('electron').BrowserWindow
|
上記のコードでは、mainWindow.loadURL
メソッドでindex.htmlファイルを読み込むように記述したので、index.htmlファイルを作成する(リスト6)。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello Electron</title>
</head>
<body>
<h1>はじめてのElectronアプリ</h1>
</body>
</html>
|
ここまでできたら、取りあえずプログラムとして動作できるので、以下のようにコマンドを実行してみよう。
electron .
|
electron
コマンドが実行されて、ウィンドウが表示されたのが確認できただろう(図1)。本連載でコードを実行するときには、基本的にこのコマンドを実行している。
Webアプリと同様にHTMLやJavaScriptのコードを記述するだけでアプリが作れることがご理解いただけたのではないだろうか。
アーキテクチャ(実行の仕組み)
取りあえずElectronのひな型アプリを動かすところまでできたが、実際の開発時には「Electronアプリがどのようにして実行されているのか」という知識も必要だろう。そこで、その仕組み/アーキテクチャ(図2)について簡単に紹介しておこう。
electron
コマンドを実行すると、package.jsonファイル内のmain
に記述されているJavaScriptファイル(本稿の例では“index.js”)をメインプロセスとして起動する。
先ほどの例では、index.jsファイルのloadURL
メソッドによりindex.htmlファイルを読み込んでHTMLページを表示していたが、これをレンダラープロセスと呼ぶ。
レンダラープロセスとメインプロセスは、IPC(Inter-process Communication:プロセス間通信)で対話する。レンダラープロセスを複数起動したときも、レンダラープロセス間の直接対話は許可されていないため、メインプロセス経由での対話となる。
このアーキテクチャは、Chrome(Chromium)で採用されているものそのものである。
プロセスの種類ごとに呼び出せるAPIが違っているので、それぞれ何が呼び出せるのかを解説していこう。
API機能解説
ElectronのAPIは大きく、
- メインプロセス
- レンダラープロセス
- 両方
で使えるものの3つに分類される。各APIはAPIリファレンスで解説されていて、一部は有志によって日本語に翻訳されているが、情報の更新が追いついていないものもあるので、英語版も併せて確認してほしい。
以下では、プロパティにアクセスした結果で取得できるクラスは省略するので、全クラスを参照したい場合は、APIリファレンスを参照していただき、ここでは直接取得できるオブジェクトを紹介する。
メインプロセスとレンダラープロセスの両方で使えるAPI
API名 | 主な機能内容 |
---|---|
clipboard | システムのクリップボードを使ってコピー/ペーストする |
crashReporter | 任意のサーバーにクラッシュレポートを送信できる |
nativeImage | PNG/JPGファイルを使って、トレイ/ドック/アプリケーションのアイコンを生成する |
process | Node.jsのprocess オブジェクトを拡張したもの |
screen | 画面のサイズ、ディスプレイの数、カーソルの位置などを取得する |
shell | ファイルの操作や、デフォルトのアプリケーションでURLを開くなど |
メインプロセスからのみ利用できるAPI
API名 | 主な機能内容 |
---|---|
app | アプリケーションが起動した、ウィンドウが全て閉じられたなど、アプリケーション全体に影響するイベントを処理する |
autoUpdater | Squirrelフレームワークへのインターフェースを提供して、アプリケーションの自動更新を可能にする。ただし現時点ではWindowsとmacOSで別の実装にする必要があり、Linuxには対応していない |
BrowserWindow | ウィンドウ(レンダラープロセス)の作成と制御をする |
contentTracing | パフォーマンスのボトルネックと遅くなる操作を見つけるために、Chromiumのコンテンツモジュールからトレースデータを収集する |
dialog | ファイルの保存やアラートなどOS標準のダイアログを表示する |
globalShortcut | アプリケーションで使用するキーボードショートカットの登録と解除をする |
ipcMain | メインプロセスからレンダラープロセスへの非同期通信をするインターフェース。レンダラープロセス側はipcRenderer (後述) |
Menu | ネイティブの(メニューバーの)メニューとコンテキストメニューを作成する |
net | HTTP/HTTPSリクエストを行う |
powerMonitor | サスペンド、復旧、AC、バッテリーなどの電源状態の変更をモニターする |
powerSaveBlocker | システムがスリープモードに入らないようにブロックする |
protocol | カスタムプロトコル(URL Scheme)を登録する |
session | ブラウザーのセッション、クッキー、キャッシュ、プロキシー設定などを管理する。Webページを要求するWebRequest クラスにもここからアクセスできる |
systemPreferences | システム設定の変更を制御できる。OSごとにアクセスできるメソッドが異なるので注意が必要だ |
Tray | システムの通知領域にアイコンとコンテキストメニューを追加する |
webContents | BrowserWindowで表示しているWebページを制御する |
レンダラープロセスからのみ利用できるAPI
API名 | 機能内容 |
---|---|
desktopCapturer | デスクトップのイメージやビデオ、オーディオなどをキャプチャできる |
ipcRenderer | メインプロセスと通信するためのインターフェース。メインプロセスのipcMain (前述)で受信できる |
remote | メインプロセスのモジュールをレンダラープロセスから使う。メインプロセスのみ利用可能なモジュール(前述のapp など)をIPCで依頼することなく、レンダラープロセスから操作できる |
webFrame | 現在表示しているWebページのレンダリングをカスタマイズする |
window.open関数 | 新しいウィンドウを開いてURLに遷移する |
プラットフォームごとの実装
Electronは、マルチプラットフォームのフレームワークなので、一度書くと、基本的にはどのプラットフォームでも実行できるが、プラットフォーム固有の記述や、プラットフォームの標準に則した実装が必要になる場面がある。その場合、process.platform
プロパティから返される文字列を比較することで(リスト8)、実行されているプラットフォームを判別できる。
if (process.platform === 'darwin') // macOS
if (process.platform === 'win32') // Windows
if (process.platform === 'linux') // Linux
|
Electronでウィンドウを表示するアプリを開発したときに、必ずと言っていいほど記述するのが以下のコードだ。
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
|
ウィンドウが全て閉じられたとき(window-all-closed)に、macOS(darwin)の場合はプロセスを残すが、それ以外のプラットフォームではアプリを終了させる。
全てのウィンドウを閉じたときには、window-all-closed
イベントが発生する。macOS(darwin)の場合は、全てのウィンドウが閉じられてもプロセスは残して、Dockに残しておくが、それ以外のプラットフォームでは、app.quit
メソッドでプロセスを終了させる。
このようにプラットフォームごとに動作を変更したい場合は、process.platform
で、実行しているプラットフォームを判断して処理を切り替えればよい。
まとめ
今回は、Electronの概要とアーキテクチャ、それぞれのプロセスで利用可能な機能を解説した。次回は、Electronのデモアプリを使って、Electronでできることを紹介していく。
1. 【現在、表示中】≫ Electronとは? アーキテクチャ/API/インストール方法/初期設定
Windows/macOS/Linuxで実行できるデスクトップアプリをWeb技術で作ろう! Electronの概要から開発を始めて動かすところまでを解説する。
2. Electron APIデモから学ぶ実装テクニック ― ウィンドウ管理とメニュー
Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はウィンドウ管理とメニューの実装方法を基礎から説明する。
3. Electron APIデモから学ぶ実装テクニック ― ネイティブUIと通信
Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はネイティブUIと通信の実装方法を基礎から説明する。
4. Electron APIデモから学ぶ実装テクニック ― システムとメディア
Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はシステムとメディアの実装方法を基礎から説明する。