clojureでelectronアプリを作ろう
TRANSCRIPT
ClojureでElectronアプリつくろう
{:company “Greative GK” :name “Kazuhiro Hara” :twitter “kara_d” :github “https://github.com/karad”}
Electron(旧:Atom-Shell)勉強会 #1
#atom_shelldescjop.org
自己紹介
2
原 一浩ハラ カズヒロ
ClojureScript + Electronのプロジェクトテンプレdescjopの作者
http://greative.jp/
( @kara_d )
http://descjop.org/
#atom_shelldescjop.org
ちょっと前の著書➡ Play Framework 2徹底入門 - JavaではじめるアジャイルWeb開発
3
実践編(4章~7章)を担当
✦サンプルアプリの企画から設計、構築、テスト、管理画面作成までを一通り
マニュアルにはない詰まりポイントとかもちりばめられてます。
#atom_shelldescjop.org
アジェンダ➡ Clojureについて➡ ビルドツールについて➡ ClojureでElectronアプリをつくるには➡ demo➡ Clojureならでは話➡ ClojureScript & Node.jsハマりどころ➡ 今後の課題
4
#atom_shelldescjop.org
Clojureってなに? ➡ Lisp方言
S式
データとしてのコード成長可能な言語
➡ 関数型プログラミング第一級関数イミュータブルなデータ構造
6
(println (+ 1 2 3)) ; => 6
#atom_shelldescjop.org
Clojureってなに? ➡ 豊かなビルド環境
LeiningenREPLClojarsJavaのライブラリ or Nodeのライブラリ
➡ 複数のビルドターゲットJava環境JavaScript環境.NET環境
7
#atom_shelldescjop.org
Clojureあれこれ ➡ Clojureは新しいけど、すごく古くもある
Clojureが生まれたのは、2007年LISPは、2番目に古い高級言語
➡ ClojureScriptはJavaScript向けコンパイル環境JavaとJavaScriptの関係とは、ちがう同一シンタックスで書ける拡張子は、Clojureが.clj、ClojureScriptが.cljs
➡ ClojureScriptは、AltJSとしては、そこそこ古いJun 3, 2011に最初のコミット
8
#atom_shelldescjop.org
LightTableはClojureScript製➡ かなりの実用度!!
9
#atom_shelldescjop.org
Clojureは読みやすい(他のLispよりちょっとだけ)
➡ JavaScript
➡ Clojure
10
function hoge (param) { console.log(“Hello world!”);}
(defn hoge [param] (println “Hello world!”))
#atom_shelldescjop.org
Clojureを選んで何がいいのか➡ フロントエンドのJavaScript、バックエンドのJVMベースサーバを強力な言語機能で統一的に作り上げることができる
11
Clojure
WebJVMServer Electron
APIAPI
#atom_shelldescjop.org
ビルドツールについて➡ ClojureとClojureScriptのビルドツール、LeiningenNode、Npm、Grunt/Gulp/Bowerやテストランナーがくっついたようなもの
13
$ lein new アプリ名
$ lein cljsbuild
$ lein test
#atom_shelldescjop.org
ClojureScriptのコンパイル➡ project.clj
ビルド情報を書くpackage.jsonみたいなもの
➡ lein-cljsbuildを使うleinコマンドからClojureScriptのコンパイルができる
➡ ClojureScriptのコンパイルGoogle Clojure関係がライブラリとして使われていたり、コンパイラとして使われたりしている
14
$ lein cljsbuild once
#atom_shelldescjop.org
JavaScriptにコンパイルされた時のサイズ➡ :optimizations :simple
400KB~2MBくらいになっちゃうこれは重い
➡ :optimizations :advanced数十から百KB程度これならなんとか
15
#atom_shelldescjop.org
Electronアプリ用のLeiningenツール
➡ http://descjop.org➡ リリース後の顛末
公開したのが4/17その日にAtom-Shell -> Electronリポジトリも変更Gruntタスク周りで本家にissue作成無事パッチが当てられ、再リリース
17
#atom_shelldescjop.org
ClojureでElectronアプリをつくるには➡ descjop.orgを使って開始すると楽
➡ 使ってみて良い感じだったら★ください~
18
$ lein new descjop アプリ名
#atom_shelldescjop.org
何が生成されるのか?
19
├── README.md├── app│ ├── index.html // トップページ│ ├── js│ │ └── main.js│ └── package.json // アプリ用package.json
├── package.json // コンパイル用package.json
├── project.clj // Clojureのコンパイル設定└── src └── NAMESPACE └── core.cljs // ClojureScriptを置く
#atom_shelldescjop.org
descjopのしくみ : その1➡ lein cljsbuildをすると、src/###/core.cljsがapp/js/cljsbuild_main.jsとしてコンパイルされる
/src/###/core.cljs
↓ コンパイル
/app/js/cljsbuild_main.js
20
#atom_shelldescjop.org
descjopのしくみ : その2➡ cljsbuild_main.jsは、app/js/main.jsから呼ばれる
/app/js/cljsbuild_main.js
↑ 呼ぶ
/app/js/main.js
21
#atom_shelldescjop.org
descjopのしくみ : その3➡ Electronは、app以下のpackage.jsonを通じてmain.jsを呼び出す
/app/js/cljsbuild_main.js
↑ 呼ぶ
/app/js/main.js
↑ 呼ぶ
/app/package.json22
#atom_shelldescjop.org
descjopのしくみ : その4➡ cljsbuild_main.jsからは、BrowserWindowとして、index.htmlをloadUrlする
/app/index.html
↑ ロードする
/app/js/cljsbuild_main.js
23
#atom_shelldescjop.org
Electron、ClojureとClojureScriptの関係
24
Clojure界
ClojureScript界
JavaScript界
Electron界
COMPILE
マクロなど
.clj.cljs.jsAPI
Leiningenによる
#atom_shelldescjop.org
demo
26
$ npm install -‐g grunt-‐cli
$ npm install
$ grunt download-‐electron
$ lein externs > app/js/externs.js
$ ./electron/Electron.app/Contents/MacOS/Electron app 5
4
3
2
1
$ lein new descjop アプリ名
#atom_shelldescjop.org
ビルド終了後の構成
27
├── README.md├── app│ ├── index.html // トップページ│ ├── js│ │ ├── cljsbuild-‐main.js // コンパイル済JS
│ │ ├── externs.js│ │ └── main.js│ └── package.json // アプリ用package.json
├── package.json // コンパイル用package.json
├── project.clj // Clojureのコンパイル設定└── src └── NAMESPACE └── core.cljs // ClojureScriptを置く
#atom_shelldescjop.org
こんな構文あったらいいな➡ appに対して、イベントハンドラ設定めんどい➡ こんな構文が欲しいとする
29
(var的なもの app名 app生成 :イベントハンドラ (関数)
:ほかのハンドラ (関数)
... ...)
#atom_shelldescjop.org
ちょいとマクロ➡ マクロは、ClojureScriptではなく、Clojureとして書く
➡ ただし、関数でできる場合は関数で書こう
30
(defmacro defatomshellapp [name app & clauses] `(loop [cl# [~@clauses]] (if (and (not (nil? cl#)) (first cl#) (next cl#)) (do (.on ~app (name (first cl#)) (second cl#)) (recur (next (next cl#)))) (defonce ~name ~app))))
#atom_shelldescjop.org
こんな風に呼び出せる➡ 欲しかった構文を拡張できる
31
(defatomshellapp app (nodejs/require "app") :ready (fn [] ( 処理 ))
:window-‐all-‐closed (fn [] ( 処理 ))))
#atom_shelldescjop.org
注意ポイント➡ externs
advancedオプションにてサイズを小さくするときに、必要な変数名などの書き換えをさせないための指定js/externs.jsとかに記述するlein-externsを使うと楽
33
$ lein externs > app/js/externs.js
#atom_shelldescjop.org
注意ポイント➡ externs
js/externs.jsは、こんな風になる
34
var TopLevel = {"BrowserWindow" : function () {},"console" : function () {},"loadUrl" : function () {},"log" : function () {},"on" : function () {},...}
#atom_shelldescjop.org
注意ポイント➡ nodeモジュール関係
node関係のモジュールもexternsすることpackage.jsonに
project.cljに
35
:externs ["app/js/externs.js""node_modules/closurecompiler-‐externs/path.js""node_modules/closurecompiler-‐externs/process.js"]
"closurecompiler-‐externs": "^1.0.4"
#atom_shelldescjop.org
注意ポイント➡ pathまわり
開発時と、ネイティブアプリケーションとしてパッケージングした時の取得可能なパスがメソッドによって異なるので注意
36
(str "file://" (.resolve path (js* "__dirname") "../index.html"))
#atom_shelldescjop.org
注意ポイント➡ その他
よくJavaScriptの関数を渡す場面で、へんなものが渡るときがある。きちんと無名関数を渡そうオブジェクトは、clj->jsを使って渡す
37
(clj-‐>js {:width 800 :height 600})
#atom_shelldescjop.org
今後の課題➡ NW.js用のスカフォルディングの提供➡ gruntタスクからgulpへの移行➡ UI周りで構成をいろいろ考え中➡ 今は遊びがてら学習サイクルまわし中
38
学ぶ
作る問う
ありがとうございました!!
Electron(旧:Atom-Shell)勉強会 #1
ClojureでElectronアプリつくろう
{:company “Greative GK” :name “Kazuhiro Hara” :twitter “kara_d” :github “https://github.com/karad”}