Ubuntu DesktopにElectron環境を構築する

##はじめに
本投稿は、Ubuntu linux のデスクトップに、Electronの開発環境を構築してみた備忘録です。
WindowsやMacの構築事例は沢山ありますが、Ubuntuの記事は少ないかも。
Electronの開発は、現状黒い画面とお友達になる必要があるので、Ubuntuとの相性が良いのですが、WindowsにもBashが公式に移植されるそうなので、優位性は少し薄まりそうで、何だか複雑な今日このごろです。
※更新するにあたって、[ElectronのクイックスタートでCannot find module 'app'にハマった件](http://qiita.com/koga1020/items/6733de8ae1b8b6782e1c)を参考にしました。

###Electron
Electronは、Githubが主導して開発しているHTMLでデスクトップアプリケーションを作成するフレームワークです。
HTMLを使ってアプリケーションを構築するというアイディア自体は、結構昔から有って、近年はスマートフォン向けのフレームワークが先行していました。
HTMLというフロント構築言語の進化は目覚ましい進化を遂げていましたので、人材、開発環境、ライブラリなどの分厚いリソースをアプリケーション開発にも転用したいというニーズは大きいのでしょう。
ただ、スマートフォンにはAppleという少し素行に問題のある会社がメインプレイヤーとして一角を占めいているためWebViewに対して制約がつきまといます。
そのためネイティブアプリと比べるとパフォーマンスが悪く使いものにならない期間が長く続いてきました。
近年はスマートフォンの性能が上がったためハイブリッドアプリも増えているようですが、主流ではありません。
Google ChromeというオープンソースWebブラウザがシェアを獲得する過程で、Node.jsという面白いソフトウェアが誕生します。
HTMLに動きを与えるためのスクリプトに過ぎなかったJavaScriptが、独立した言語としてサーバーサイドやデスクトップで動作するようになったのです。
Node.jsは、V8というスクリプトエンジンのみを再利用したプロダクトでしたが、Webブラウザごとデスクトップアプリケーション基盤として再利用したのが、Electronです。
このアイディアは、Github社独自のアイディアではなく、Adobe社も少し前に実現しています。
後発の似たようなアイディアでしたが、Githubという開発者に圧倒的な支持を得ている企業が開発したElectronは、あっという間に広がりました。
(Adobe社は、ちょっと不憫でしたね。開発者に好かれて無いんだなぁ)
現在ネイティブアプリケーションの開発は、Windowsであれば、XAML/C#などで行われることが多いと思いますが、次世代は、HTML/JavaScriptになる公算が高いと思われます。
Electronは、次世代環境に最も近い開発環境だと思います。（個人的見解）

##何はともあれNode.jsをインストール
Electronをビルドするには、Node.jsを利用します。基本的にはこれだけで良いのでシンプルでいいですね。
Ubuntuには、素の状態ではNode.jsは居ませんので、下記のコマンドには反応しない筈です。
必ずしも最新のNode.jsは必要無いと思いますが、nodebrewで最新環境にするには、まずアンインストールしてください。

```:command
$ node -v
```
nodebrewは、Node.jsのバージョンを管理するソフトです。
最新版をインストールしてもNode.jsは更新が早いためnodebrewでインストールしておけば、置き換えが簡単になります。
また、最新版にして不具合が発生しても直ぐに前のバージョンへ戻すことが可能になります。

```:command
$ curl -L git.io/nodebrew | perl - setup
```
インストール後に、パスを通す必要があります。
私は、.profileの最終行へ追加しました。

```:.profile
・・・
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

```:command
$ vi ~/.profile
$ source ~/.profile
$ echo $PATH
```
次のコマンドで、インストール可能なバージョンの一覧を表示します。
[本家サイト](http://electron.atom.io/)を確認するとElectronに内蔵されているNode.jsのバージョンは、v6.5.0のようなので、Electronに合わせるか、LTSのv6.9.4を利用するのが安心です。
執筆時最新バージョンのv7.4.0でも試して見ましたが、新しすぎてエラーが表示されました。

```:command
$ nodebrew ls-remote
```
インストールは、下記のコマンドで行います。

```:command
$ nodebrew install-binary v6.9.4
```
インストールされているバージョンを確認します。

```:command
$ nodebrew ls

nodebrew ls
v6.9.4

current: none
```
`current: none`となっているので、まだ利用できる状態ではありません。
次のコマンドで、使用できるように設定する。

```:command
$ nodebrew use v6.9.4
$ node -v
v6.9.4
```

##Electron環境の構築
適当なフォルダを作成して、`npm init`を実行して、package.jsonを作成します。
Electronの本体のelectron-prebuiltとリリース用のパッケージを作成するelectron-packagerをインストールします。
パッケージは、他のelectronプロジェクトと共有できるモジュールなので、グローバルにインストールします。
※グローバルにインストールしたモジュールは、require()でloadできないとエラーになることがあります。その場合にはパスが通ってないので、NODE_PATH環境変数を設定します。グローバルインストール用フォルダは、`npm bin -g`コマンドで、確認できます。
[npm と Node.js 上で require を使ったモジュール読み込みの仕組みについてメモ](http://phiary.me/npm-node-js-require-module-memo/)
※electron-prebuiltのパッケージ名は、非推奨になりelectronへ統一されるみたいなので修正しました。

```:command
$ npm init
$ npm -g install electron
$ npm -g install electron-packager
```
scriptsの部分にbuildコマンドを記述します。

```:package.json
"scripts": {
    "build": "node_modules/.bin/electron ."
}
```
最初に実行されるindex.html,index.jsを作成します。

```:index.js
"use strict";

const electron = require("electron");
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;

// 全てのウィンドウが閉じたら終了
app.on('window-all-closed', function() {
  if (process.platform != 'darwin') {
    app.quit();
  }
});
// Electronの初期化完了後に実行
app.on('ready', function() {
  // メイン画面の表示。ウィンドウの幅、高さを指定できる
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadURL('file://' + __dirname + '/index.html');

  // ウィンドウが閉じられたらアプリも終了
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});
```

```:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>DemoApp</title>
    <meta name="description" content="">
    <meta name="keywords" content=""/>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="style.css">
</head>
<body ng-app="app" ng-controller="RootCtrl as root">
<h1>Test App</h1>
</body>
</html>
```
ビルドを行います。

```:command
$ npm run build
```

##リリース
リリースを行うためのスクリプトを追加します。

```:package.json
"scripts": {
    "build": "node_modules/.bin/electron .",
    "release": "node release.js"
}
```

```:release.js
const packager = require('electron-packager');
const config = require('./package.json');
 
packager({
    dir: './',
    out: '../release',
    name: config.name,
    platform: 'linux',
    arch: 'x64',
    version: '1.4.14',
    icon: './app.icns',
 
    'app-bundle-id': 'jp.co.test.test',
 
    'app-version': config.version,
    'helper-bundle-id': 'jp.co.test.testapp',
    overwrite: true,
    asar: true,
    prune: true,
    ignore: "node_modules/(electron-packager|electron-prebuilt|\.bin)|release\.js",
    'version-string': {
        CompanyName: '会社名',
        FileDescription: 'アプリケーションの説明',
        OriginalFilename: config.name,
        FileVersion: config.version,
        ProductVersion: config.version,
        ProductName: config.name,
        InternalName: config.name
    }
}, function done (err, appPath) {
    if(err) {
        throw new Error(err);
    }
    console.log('Done!!');
});
```
リリースビルドを行います。

```:command
$ npm run release
```

../release/test-linux-x64配下に、アプリケーションが作成されます。
結構簡単ですね。
次は、アプリケーションとしての機能を実装していきたいと思います。