Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
Electronデスクトップアプリ開発入門(1)

Electronデスクトップアプリ開発入門(1)

Electronとは? アーキテクチャ/API/インストール方法/初期設定

2017年1月31日

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 CodeSlackはだいたい想像が付くだろうが、ターミナルの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)。

Bash
npm install electron -g
リスト1 npmコマンドでElectronをインストールする

 npmコマンドに-gオプションを付けることで、グローバルインストールされるため、今後のインストールは不要になる。

アプリの初期設定とウィンドウの表示

 最初のアプリを作成してみよう。

 まずはアプリのフォルダーを作成する(リスト2)。

Bash
mkdir myapp01
cd myapp01
リスト2 アプリのディレクトリを作成する。

 次にアプリの初期設定をするために、npm initコマンドを実行する。リスト3に示すように、npm initを実行すると、対話によって初期設定が行える。

Bash
$ npm init

name: (myapp01) ↙️
version: (1.0.0) ↙️
description: はじめてのElectronアプリです。↙️
entry point: (index.js) ↙️
test command: ↙️
git repository: ↙️
keywords: ↙️
author: 尾崎義尚↙️
license: (ISC) ↙️
リスト3 npm initコマンドによりアプリの初期設定をする。

括弧内に表示されているデフォルト値のままでよい場合は、Enterキーを押すだけでよい。

 この上記の対話によって、リスト4の内容のpackage.jsonファイルが作成される。ここで細かく設定しなくても後からpackage.jsonファイルの記述を変更すればよいだけなので、最初は全てEnterキーだけでデフォルト値で作成してもよいだろう(なお、npm init -yコマンドを実行すれば、全てEnterキーを押した場合のpackage.jsonファイルが作られる)。

JSON
{
  "name": "myapp01",
  "version": "1.0.0",
  "description": "はじめてのElectronアプリです。",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "尾崎義尚",
  "license": "ISC"
}
リスト4 npm initコマンドで生成されたpackage.jsonファイル

 エントリーポイント(package.jsonファイルの記述ではmain)として指定されたindex.jsファイルは自動では作成されないので、手動で作成する。ウィンドウを表示するために、index.jsファイルにリスト5のコードを記述していく。

JavaScript
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
  })
})
リスト5 アプリの起動とウィンドウを表示するためにJavaScriptのコードを記述する(index.js)

 波かっこで代入する記述は、分割代入と呼ばれ、右辺のオブジェクトからプロパティ値を代入する記述方法である。以下の記述も同様の意味となり、Electronのサンプルコードは混在していることがあるため、両方を覚えておくとよい。本稿でも混在して記述している。

JavaScript
const app = require('electron').app
const BrowserWindow = require('electron').BrowserWindow
分割代入を「しない」場合の書き方

 上記のコードでは、mainWindow.loadURLメソッドでindex.htmlファイルを読み込むように記述したので、index.htmlファイルを作成する(リスト6)。

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello Electron</title>
</head>
<body>
  <h1>はじめてのElectronアプリ</h1>
</body>
</html>
リスト6 アプリの起動とウィンドウを表示するためにJavaScriptのコードを記述する(index.html)

 ここまでできたら、取りあえずプログラムとして動作できるので、以下のようにコマンドを実行してみよう。

Bash
electron .
リスト7 作成したプログラムをelectronコマンドで実行する

 electronコマンドが実行されて、ウィンドウが表示されたのが確認できただろう(図1)。本連載でコードを実行するときには、基本的にこのコマンドを実行している。

図1 コマンドを実行するとウィンドウが表示される

 Webアプリと同様にHTMLやJavaScriptのコードを記述するだけでアプリが作れることがご理解いただけたのではないだろうか。

アーキテクチャ(実行の仕組み)

 取りあえずElectronのひな型アプリを動かすところまでできたが、実際の開発時には「Electronアプリがどのようにして実行されているのか」という知識も必要だろう。そこで、その仕組み/アーキテクチャ(図2)について簡単に紹介しておこう。

図2 Electronのアーキテクチャ(実行の仕組み)

 electronコマンドを実行すると、package.jsonファイル内のmainに記述されているJavaScriptファイル(本稿の例では“index.js”)をメインプロセスとして起動する。

 先ほどの例では、index.jsファイルのloadURLメソッドによりindex.htmlファイルを読み込んでHTMLページを表示していたが、これをレンダラープロセスと呼ぶ。

 レンダラープロセスとメインプロセスは、IPCInter-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)、実行されているプラットフォームを判別できる。

JavaScript
if (process.platform === 'darwin')   // macOS
if (process.platform === 'win32')    // Windows
if (process.platform === 'linux')    // Linux
リスト8 process.platformで実行中のプラットフォームを判別できる

 Electronでウィンドウを表示するアプリを開発したときに、必ずと言っていいほど記述するのが以下のコードだ。

JavaScript
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
リスト9 全てのウィンドウが閉じられたイベント(window-all-closed)の記述(index.js)

ウィンドウが全て閉じられたとき(window-all-closed)に、macOS(darwin)の場合はプロセスを残すが、それ以外のプラットフォームではアプリを終了させる。

 全てのウィンドウを閉じたときには、window-all-closedイベントが発生する。macOS(darwin)の場合は、全てのウィンドウが閉じられてもプロセスは残して、Dockに残しておくが、それ以外のプラットフォームでは、app.quitメソッドでプロセスを終了させる。

 このようにプラットフォームごとに動作を変更したい場合は、process.platformで、実行しているプラットフォームを判断して処理を切り替えればよい。

まとめ

 今回は、Electronの概要とアーキテクチャ、それぞれのプロセスで利用可能な機能を解説した。次回は、Electronのデモアプリを使って、Electronでできることを紹介していく。

Electronデスクトップアプリ開発入門(1)
1. 【現在、表示中】≫ Electronとは? アーキテクチャ/API/インストール方法/初期設定

Windows/macOS/Linuxで実行できるデスクトップアプリをWeb技術で作ろう! Electronの概要から開発を始めて動かすところまでを解説する。

Electronデスクトップアプリ開発入門(1)
2. Electron APIデモから学ぶ実装テクニック ― ウィンドウ管理とメニュー

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はウィンドウ管理とメニューの実装方法を基礎から説明する。

Electronデスクトップアプリ開発入門(1)
3. Electron APIデモから学ぶ実装テクニック ― ネイティブUIと通信

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はネイティブUIと通信の実装方法を基礎から説明する。

Electronデスクトップアプリ開発入門(1)
4. Electron APIデモから学ぶ実装テクニック ― システムとメディア

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はシステムとメディアの実装方法を基礎から説明する。

Electronデスクトップアプリ開発入門(1)
5. Electronアプリのデバッグと、パッケージ化

本格的にElectronアプリ開発を進める方に向けて、そのデバッグ方法と、製品リリースのためのパッケージ作成の方法について説明する。

サイトからのお知らせ

Twitterでつぶやこう!