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コードを入力し、テスト
- 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/");
- Node.jsでapp.jsを実行し、指定したIP (http://127.0.0.1:1337)で確認
Electronのインストール
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 initでpackage.jsonを作成
- 何を言ってるのか全然理解できなかったら、ただEnterだけ押せばほとんどOK
(ここではプロジェクト名をelectronに設定する) ただ、entry pointには必ず「main.js」を設定すること!- entry pointはindex.jsでも構わない(2019/06/04追記)
- もしpackage.jsonにmain scripttが設定されてない場合、
Electronは自動で同じディレクトリーのindex.jsをロードする
- 上の作業で、下のような「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」みたいな物を出力してみよう。
initでmain scriptを「main.js」**で設定したので、main.jsから作成することに。
/**
* main.js
**/
// アプリケーション基盤をコントロールするモジュール
const {app} = require('electron');
// ブラウザーウィンドーを作るモジュール
const {BrowserWindow } = require('electron');
// ウィンドーオブジェクトを全域に維持
let 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.jsがindex.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。
実行してみよう。
Packaging
-
プロジェクトを誰でも使えるように、パッケージ化してみよう。
-
ここでは、electron-packagerを使って作業。
これもnpmでもってこればOK
これでダウンロード終わり。
-
早速使ってみよう
この通り、electron-win32-ia32とelectron-win32-x64フォルダが生成された。
書いた内容を説明すると…platform : all, linux, win32, darwin
arch : all, ia32, x64
version : 今は要らなくなったので、上のScreenShotに書いてあるのは無視
electron-version : electronのversionを記載(2019/06/04 追記)
※electronのversionは、electron --version
で確認可能ここでallを選んだので、フォルダが32と64の二つができた。
もし32bitWindowsの装置を使ってるとしたら、実は
electron-packager ./electron electron --platform=win32 --arch=ia32 --electron-version=1.4.13
これでOK。 -
実行
プロジェクト名をElectronにしてしまって、ちょっとわかり辛くなったが…
こうやってEXEファイルができ、それを実行したら普通にアプリが動く。
Electronでのアプリケーション開発
0. Source Code
- これを書いてから時間もたって、Electronにもちょっと変化があった。
- 自分のGithubに新バージョンのソースを載せといたので、それを参照
- Electron-Notepad
1. 目標
- 簡単なメモ帳アプリの作成 (テキストの保存とロード機能)
- WindowsでElectronを使うこと
- プロジェクト作成にはAtomとGruntを使ってみること
- パッケージングで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」設定)
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 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
3-2. プロジェクトソース
- 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": {
"electron": "^1.6.11",
"grunt": "^0.4.5",
"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",
"moment": "^2.8.3",
"time-grunt": "^1.3.0"
}
}
- main.js
/**
* main.js
**/
'use strict';
const {app, BrowserWindow} = require('electron');
let 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.jsonにdevDependenciesとして定義されているmoduleを全部インストールする。
-
C:\PROJECT
にてnpm install
- Atom Minifyでmemo.min.js作成
- atom-minifyの設定で「Minify on save」を設定すると、保存する時に自動でmemo.min.jsを生成
- この画面が出ればOK。
- Grunt RunnerでGruntをDefaultで動かす
- Gruntは勉強用で入れたのがほとんどで、実際この作業で必須なのはincludesだけ。
- link.html、memo.htmlをindex.htmlに含め、/app/view/index.htmlを作成
- この画面が出ればOK。
-
C:\PROJECT
にてelectron memo/
で動作確認 - この画面が出ればOK。
4. パッケージング・動作確認
4-1. パッケージング
- memoフォルダをmemoMK2という名前でパッケージングする。
C:\Users\idenr\project>electron-packager ./memo memoMK2 --platform=win32 --arch=x64
Packaging app for platform win32 x64 using electron v1.6.11
Wrote new app to C:\Users\idenr\project\memoMK2-win32-x64
4-2. 作動確認
まとめ
すごく簡単!
- Web Pageを作る感覚で、普通にDesktop Applicationが作れる。
- 環境設定に時間がかからないのもメリット
- 以前のHadoopの時を考えたら…
- 特にWindowsでも簡単にできるのが嬉い。
Creatorとしての喜び
- こうやって簡単にアプリを作れるから、創作意欲が沸く。
- 自分に必要な物は、自分で作ってみよう!