도쿄사는 외노자

[차후 한글화 예정] Electron 첫걸음 본문

Tech/Electron

[차후 한글화 예정] Electron 첫걸음

Enrai 2017. 4. 20. 09:43

Electron

Electronとは

  • 旧)Atom Shell

  • Node.jsに基づいたDesktop Application Flatform

    • HTML, CSS, JavaScriptで、Cross-Flatformで 動くDesktop Applicationを作れる

    • WebPageのGUIとjavascriptで操作するChromium Browser

  • Desktop Application : 似た技術としてNW.js (node-webkit)が存在

    • 技術的な違いについては、ここを参考
  • Electronで作られたアプリについては、 Awesome Electron 参照

環境構築手順

目標

  • WindowsでのElectron開発環境構築

  • ElectronでHello Worldの出力

  • パッケージングでexeファイルを作成、動作確認

基本設定

  • 装置1スペック

    • CPU : i3-4000M 2.40GHz

    • RAM : 4.0GB

    • OS : Microsoft Windows 8.1 Enterprise K 64Bit

    • Electron Version: 0.36.8

  • 装置2スペック

    • CPU : i3-3240 3.40GHz

    • RAM : 4.0GB

    • OS : Microsoft Windows 7 Professional SP1 32Bit

    • Electron Version: 0.36.8

下準備

  • Node.js : Stable Version (v.5.7.1)

    • npmを使うので、Node.jsの設置は必須!

    • Windowsのバージョンに合わせて、msiファイルをダウンロードし、設置するだけでOK

  • Node.jsの設置確認

    • cmd > node

    • 簡単なjavascriptコードを入力し、テスト

cmdTest.png

  • jsファイルでのテスト : app.js (エンコード:UTF-8)

var http = require('http');

 http.createServer(function(req,res){

   res.writeHead(200,{'Content-Type':'text/plain'});

   res.end('Hello World\nHello node.js!');

 }).listen(1337,"127.0.0.1");



 console.log("Server running at http://127.0.0.1:1337/");

nodeJSTest2.png

Electronのインストール

  • npmを使って、electron-prebuiltをダウンロード

  • Globalで設置したので、どこでプロジェクトを作成しても「electron プロジェクト名/」で実行できる。

inst.png

Electronの実行

Electron Appの構造


your-app/

├── package.json : main fieldにscript fileを指定し、main processのエントリーポイントとして使用

├── main.js      : Windowを作り、システムイベントを処理

└── index.html   : ユーザに見せるページ

プロジェクト生成

  • Electronは、実行されるときに「package.json」のmain scriptを呼び出す。

    • main script:main processで作動し、GUI Component操作・Web Page生成
  • npm initpackage.jsonを作成

    • 何を言ってるのか全然理解できなかったら、ただEnterだけ押せばほとんどOK

    (ここではプロジェクト名をelectronに設定する)

    • ただ、entry pointには必ず「main.js」を設定すること!

    • もしpackage.jsonmain scriptが設定されてない場合、

      Electronは自動で同じディレクトリーのindex.jsをロードする

initProject.png

  • 上の作業で、下のような「package.json」が生成される

/**

 * package.json

 **/ 

{

  "name": "electron",

  "version": "1.0.0",

  "description": "print \"Hello, Electron\"",

  "main": "main.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "author": "Youngjae Kwon",

  "license": "ISC"

}

Hello, Electron!

一旦準備が終わったので、いつもの通り「Hello World」みたいな物を出力してみよう。

initmain script「main.js」で設定したので、main.jsから作成することに。


/**

 * main.js

 **/ 

// アプリケーション基盤をコントロールするモジュール

var app = require('app');



// ブラウザーウィンドーを作るモジュール

var BrowserWindow = require('browser-window');



// ウィンドーオブジェクトを全域に維持

var mainWindow = null;



// すべてのウィンドーが閉じられたら呼び出される (アプリケーション終了)

app.on('window-all-closed', function() {

  if (process.platform != 'darwin') {

    app.quit();

  }

});



// Electronの初期化が完了し、ブラウザーウィンドーを開く準備ができたら実行

app.on('ready', function() {

  // 新しいブラウザーウィンドーを生成

  mainWindow = new BrowserWindow({width: 800, height: 600});



  // 今のディレクトリーで「 index.html」をロード

  mainWindow.loadUrl('file://' + __dirname + '/index.html');



  // ウィンドーが閉じられたら呼び出される  (アプリケーション終了)

  mainWindow.on('closed', function() {

    // ウィンドーオブジェクトの参照を削除

    mainWindow = null;

  });

});

main.jsindex.htmlを呼ぶことにしたので、今度はindex.htmlを作成する。

実際目に見える部分はここで作成する。

  • index.html

<!--

/*

 * index.html

 */

 -->

<!DOCTYPE html>

<html>

<head>

  <meta charset="UTF-8">

  <title>Sample</title>

</head>

<body>

  <p>Hello, Electron!</p>

</body>

</html>

これで準備はOK。

実行してみよう。

sample.png

Packaging

  • プロジェクトを誰でも使えるように、パッケージ化してみよう。

  • ここでは、electron-packagerを使って作業。

これもnpmでもってこればOK

packager.png

これでダウンロード終わり。

  • 早速使ってみよう

packager2.png

この通り、electron-win32-ia32とelectron-win32-x64フォルダが生成された。

書いた内容を説明すると…

platform ・・・ all, linux, win32, darwin

arch ・・・ all, ia32, x64

version ・・・ Electronのバージョンを指定 (現在0.36.8)

ここでallを選んだので、フォルダが32と64の二つができた。

もし32bitWindowsの装置を使ってるとしたら、実は

electron-packager ./electron electron --platform=win32 --arch=ia32 --version=0.36.8

これだけでOK。

  • 実行

run.png

プロジェクト名をElectronにしてしまって、ちょっとわかり辛くなったが…

こうやってEXEファイルができ、それを実行したら普通にアプリが動く。

Electronでのアプリケーション開発

1. 目標

  • 簡単なメモ帳アプリの作成 (テキストの保存とロード機能)

  • WindowsでElectronを使ったアプリ開発

  • プロジェクト作成にはAtomGruntを使ってみること

  • パッケージングでEXEファイルを作り、動作を確認

2. 準備

2-1. Atom

  • Atom ダウンロード (https://atom.io)

    Windowsのバージョンに合わせてインストールするだけでOK

  • Packageの設置 (File→Settings→InstallでPackage検索)

    • linter : 文法上のエラー表示

    • grunt-runner : AtomでGrunt実行

    • minimap, minimap-find-and-replace : minimapが見える

    • atom-minify : JS, CSSの圧縮化 (ctrl+shift+m or 「Minify on save」設定)

package-atom.png

2-2. Grunt

  • Gruntとは?

    • プロジェクト自動化のためのCommand Line Build Tool

    • パッケージ管理者 (Yeoman , Bower , Gulp等と同じ)

    • もっとも基本的な自動化パッケージ

  • grunt-cli (Grunt's Command Line Interface) 設置

    • grunt-cliの設置で、システム経路に「grunt」コマンドが追加され、gruntが使えるようになる。

    • grunt-cliの役割はただGruntflieというファイルがある場所に設置されたGruntを実行するだけ。

grunt-cli.png

  • Grunt Module 設置方法 (package.jsonがあるディレクトリで設置)

    • 新しいModuleを設置し、package.jsonに記入 : npm install grunt --save dev

    • すでにpackage.jsonに記入されているModuleを設置 : npm install

    (package.jsonとGruntfile.jsがあれば、どこでも同じgrunt作業が可能!)

    • ここでは2の方法でプロジェクト作成

3. Project作成

3-1. ディレクトリ構成図


C:\PROJECT\MEMO

│  Gruntfile.js

│  main.js

│  package.json

│  

├─app

│  ├─css

│  │      bootstrap-theme.css

│  │      bootstrap-theme.css.map

│  │      bootstrap-theme.min.css

│  │      bootstrap.css

│  │      bootstrap.css.map

│  │      bootstrap.min.css

│  │      

│  ├─fonts

│  │      glyphicons-halflings-regular.eot

│  │      glyphicons-halflings-regular.svg

│  │      glyphicons-halflings-regular.ttf

│  │      glyphicons-halflings-regular.woff

│  │      glyphicons-halflings-regular.woff2

│  │      

│  ├─html

│  │  │  index.html

│  │  │  

│  │  └─include

│  │          link.html

│  │          memo.html

│  │          

│  ├─js

│  │  │  memo.js

│  │  │  memo.min.js

│  │  │  

│  │  └─lib

│  │          bootstrap.js

│  │          bootstrap.min.js

│  │          jquery-1.12.1.js

│  │          jquery-1.12.1.min.js

│  │          npm.js

│  │          

│  └─view

│      │  index.html

│      │  

│      └─include

│              link.html

│              memo.html

│              

├─dist

│  ├─css

│  │      style.min.css

│  │      

│  └─js

│          site.js

│          site.min.js

│          

└─node_modules

    ├─grunt

    ├─grunt-cache-breaker

    ├─grunt-contrib-cssmin

    ├─grunt-contrib-uglify

    ├─grunt-includes

    ├─load-grunt-tasks

    ├─moment

    └─time-grunt                        
  • css・fonts・libフォルダには、Bootstrap, JQueryをダウンロードして入れる。

3-2. プロジェクトソース

  • package.json

/**

 * package.json

 **/

{

  "name": "memo",

  "version": "1.0.0",

  "description": "save and load txt file",

  "main": "main.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "author": "Youngjae Kwon",

  "license": "ISC",

  "devDependencies": {

    "grunt": "^0.4.5",

    "moment": "^2.8.3",

    "grunt-cache-breaker": "^2.0.1",

    "grunt-contrib-cssmin": "^1.0.0",

    "grunt-contrib-uglify": "^1.0.0",

    "grunt-includes": "^0.5.4",

    "load-grunt-tasks": "^3.4.1",

    "time-grunt": "^1.3.0"

  }

}
  • main.js

/**

 * main.js

 **/

var app = require('app');

var BrowserWindow = require('browser-window');

var mainWindow = null;



app.on('window-all-closed', function() {

  if (process.platform != 'darwin') {

    app.quit();

  }

});



app.on('ready', function() {

  mainWindow = new BrowserWindow({width: 550, height: 410});

  mainWindow.loadUrl('file://' + __dirname + '/app/view/index.html');

  mainWindow.on('closed', function() {

    mainWindow = null;

  });

});
  • Gruntfile.js

/**

 * Gruntfile.js

 **/

module.exports = function(grunt) {

    'use strict';

    var moment = (require('moment'))();

    var timestamp = 'None';



    // 自動でgrunt Taskをロードする。(grunt.loadNpmTasksは省略可能)

    require('load-grunt-tasks')(grunt);



    // 作業時間表示

    require('time-grunt')(grunt);



    grunt.initConfig({

        pkg: grunt.file.readJSON('package.json'),



        // html task

        includes: {

            files: {

                cwd: 'app/html/',    // app/htmlのhtmlファイルにinclude処理をして

                src: ['**/*.html'],

                dest: 'app/view/',    // その結果をapp/viewに入れる

                options: {

                    flatten: true,

                    debug: true,

                    includePath: 'app/html/'

                }

            }

        },

        // css task

        cssmin: {

            options: {

                keepSpecialComments: 1,

            },

            dist: {

                src: 'dist/css/style.css',

                dest: 'dist/css/style.min.css'

            }

        },

        // js task

        uglify: {

            options: {

                banner: '<%= banner %>'

            },

            dist: {

                src: 'dist/js/site.js',

                dest: 'dist/js/site.min.js'

            }

        },

        cachebreaker: {

          dev: {

            options: {

              match: ['.js'],

              replacement: function () {

                return moment.format('YYYYMMDDhhmmss');

              }

            },

            files: {

              src: ['app/html/*.html', 'app/view/*.html']

            }

          }

        }

    });



    // html task

    grunt.registerTask('html', ['includes']);

    // css task

    grunt.registerTask('css', ['cssmin']);

    // javascript task

    grunt.registerTask('js', ['uglify', 'cachebreaker']);



    // default task

    grunt.registerTask('default', ['html', 'css', 'js']);

};
  • index.html

<!--

/*

 * index.html

 */

 -->

<!DOCTYPE html>

<html lang="ja">

<head>

  <meta charset="utf-8">

  <title>Memo MK2</title>

  <link href="../css/bootstrap.min.css" rel="stylesheet">

</head>

<body>

  include "include/link.html"

  include "include/memo.html"

</body>

</html>
  • link.html

<!--

/*

 * link.html

 */

 -->

<script src="../js/lib/jquery-1.12.1.min.js"></script>

<script src="../js/lib/bootstrap.min.js"></script>

<script type="text/javascript" src="../js/memo.min.js"></script>
  • memo.html

<!--

/*

 * memo.html

 */

 -->

<table class="table table-striped">

  <tr>

    <td style="text-align: left; width: 100px;">テキスト入力</td>

    <td colspan="2" style="text-align:left; width:300px;">

      <textarea id="ntText" class="input-xxlarge" style="width:95%; height:200px;" maxlength="4000"></textarea>

    </td>

  </tr>

  <tr>

    <td>ファイル名</td>

    <td>

      <input type="text" class="form-control"  id="nmSaveFile" />

    </td>

    <td>

      <button class="btn btn-default btn-primary" onclick="saveTxt()">保存する</button>

    </td>

  </tr>

  <tr>

    <td>ファイル選択</td>

    <td>

      <input type="file" class="form-control"  id="nmLoadFile" />

    </td>

    <td>

      <button class="btn btn-default btn-primary" onclick="loadTxt()">ロードする</button>

    </td>

  </tr>

</table>
  • memo.js

/**

 * memo.js

 **/

// テキスト保存

function saveTxt(){

  var ntText = document.getElementById("ntText").value;

  var ntBlobText = new Blob([ntText], {type:'text/plain'});

  var nmSaveFile = document.getElementById("nmSaveFile").value;

  var saveLink = document.createElement("a");

  saveLink.download = (nmSaveFile === null || nmSaveFile == "") ? "memo.txt" : nmSaveFile + ".txt";

  saveLink.innerHTML = "Download File";

  saveLink.href = window.webkitURL.createObjectURL(ntBlobText);

  saveLink.click();

}



// テキストロード

function loadTxt(){

  var nmLoadFile = document.getElementById("nmLoadFile").files[0];

  var fileReader = new FileReader();

  fileReader.onload = function(fileLoadedEvent){

    var ntLoadText = fileLoadedEvent.target.result;

    document.getElementById("ntText").value = ntLoadText;

  };

  fileReader.readAsText(nmLoadFile, "UTF-8");

}

3-3. プロジェクト作成

  • node_modules インストール

    • package.jsondevDependenciesとして定義されているmoduleを全部インストールする。

    • C:\PROJECTにてnpm install

  • Atom Minifymemo.min.js作成

    • atom-minifyの設定で「Minify on save」を設定すると、保存する時に自動でmemo.min.jsを生成

    • この画面が出ればOK。

 

success_minify.png

  • Grunt RunnerGruntDefaultで動かす

    • Gruntは勉強用で入れたのがほとんどで、実際この作業で必須なのはincludesだけ。

    • link.htmlmemo.htmlindex.htmlに含め、/app/view/index.htmlを作成

    • この画面が出ればOK。

grunt_success.png

  • C:\PROJECTにてelectron memo/で動作確認

    • この画面が出ればOK。

run_electron.png

4. パッケージング・動作確認

4-1. パッケージング

  • memoフォルダmemoMK2という名前でパッケージングする。

C:\project>electron-packager ./memo memoMK2 --platform=win32 --arch=ia32 --version=0.36.8

Packaging app for platform win32 ia32 using electron v0.36.8

Wrote new app to C:\project\memoMK2-win32-ia32

C:\project>

4-2. 作動確認

complete.png

まとめ

すごく簡単!

  • Web Pageを作る感覚で、普通にDesktop Applicationが作れる。

  • 環境設定に時間がかからないのもメリット

    • 以前のHadoopの時を考えたら…

    • 特にWindowsでも簡単にできるのが嬉い。

Creatorとしての喜び

  • こうやって簡単にアプリを作れるから、創作意欲が沸く。

  • 自分に必要な物は、自分で作ってみよう!

参考

'Tech > Electron' 카테고리의 다른 글

Electron 발표용 총정리 (보관용)  (0) 2016.03.09
Electron을 시작해 보자  (0) 2016.02.24
Windows에 Electron을 빌드하기 위한 준비  (0) 2015.10.25