Luminusを使って簡単にWeb開発したい

実際にはどうすればいいのか。
ちょっとわかってきたのでメモ。

# 方針
* サーバ側はClojureで開発
* クライアント側はClojureScriptを使いたい。JavaScriptも併用したい
* BootstrapやJQueryのコンポーネントとか、外部のJavaScriptライブラリも組み込みたい
 
# プロジェクトの作成
* Leiningenを使ったプロジェクト作成のコマンド

```
lein new luminus sample-project +postgres
```

いつものようにleinでプロジェクトを作る。
`+postgres`の部分はhttp://www.luminusweb.net/docs/profiles.md にあるものを使える。
ただし`+cljs`のClojureScript Supportはかえって難しくなるので使わない。（ここ重要）

# ClojureScriptを使うための設定
## project.cljの編集
* `:plugins`に以下を追記

```:clj
[lein-cljsbuild "1.0.3"]
```

ClojureScriptのコンパイルをするために追加する。

* `:dependencies`に以下を追記

```:clj
   [org.clojure/clojurescript "0.0-2371"]
   [cljs-ajax "0.3.3"]
```

ClojureScriptとcljs-ajaxを使う設定。
他にも使いたいライブラリがあれば追加する。

* トップレベルの箇所に以下を追記

```:clj
  :cljsbuild
  {:builds {:app {:source-paths ["src-cljs"]
                  :compiler {:output-to     "resources/public/js/app.js"
                             :output-dir    "resources/public/js/out"
                             :source-map    "resources/public/js/out.js.map"
                             :externs       []
                             :optimizations :none
                             :pretty-print  true}}}}
```

※追記：開発時は`:optimizations :none`より`:optimizations :simple`のほうがよいかもしれない

ClojureScriptのコンパイル設定。
ソースは`src-cljs`に入れて出力は`resources/public/`の下に。


* `:profiles {:uberjar {` の中に以下を追記

```:clj
             :hooks [leiningen.cljsbuild]
             :cljsbuild {:jar true
                         :builds {:app
                                  {:compiler
                                   {:optimizations :advanced
                                    :pretty-print false}}}}
```

`:omit-source true`とか書いてあるところと並列するように追加する。
`lein ring uberjar`するときにClojureScriptのコンパイルもする設定らしい。

## ソースディレクトリの作成
`src-cljs/sample_project`ディレクトリを作成する。
`sample_project`の部分はプロジェクトごとに変わる。`src`の直下と同じ。

その中にcore.cljsファイルを作成する。（ファイル名はXXX.cljsなら何でもいいけど）

# サンプルコードの作成・動作確認
## core.cljsの作成
 
```core.cljs
(ns sample-project.core
  (:require [ajax.core :refer [POST]]))

(defn ^:export init [message]
  (js/alert message))

(defn ^:export post [message]
  (POST (str js/context "/sample")
        {:params {:text1 message :value1 (rand-int 10)}
         :handler #(js/alert (:val %))}))
```

ネームスペースは適当でもいいけど、プロジェクト名.XXXをつけるのがいい。
`^:export`をつけた関数はJavaScript側からその名前で呼び出すことができる。
https://github.com/JulianBirch/cljs-ajax の`POST`関数を使うと簡単にAjaxできてすばらしい。
`:params`に入力パラメータを入れて、レスポンスは`:handler`で処理できる。
ちなみに`js/context`はbase.htmlで定義されている。

## resources/templates/base.htmlの編集

JavaScriptを読み込むため、bootstrap.min.jsを読み込んでいるscriptタグの下に以下を追記する。

```:html
    {% script "/js/out/goog/base.js" %}
    {% script "/js/app.js" %}
    <script type="text/javascript">goog.require("sample_project.core");</script>
```

`sample_project.core`の部分はClojureScriptのネームスペースと同じ。ただし、ハイフンはアンダースコアに変換しておく。
`{% script "/js/app.js" %}` のような部分はhttps://github.com/yogthos/Selmer のテンプレート

## resources/templates/home.htmlの編集

以下のようなJavaScriptを呼び出すコードを適当に入れる。

```:html
  <button type="button" class="btn btn-primary" onClick="sample_project.core.init('hello!');">Primary</button>
  <button type="button" class="btn btn-primary" onClick="sample_project.core.post('world!');">Post Sample</button>
```

`sample_project.core`の部分はbase.htmlでgoog.requireしたのと同じもの。

## src/sample_project/routes/home.cljの編集

* core.cljsからAjaxで呼び出されるサーバ側のコード

一番上のns :requireに以下を追記する。

```:clj
            [noir.response :refer [edn]]
```

一番下の`(defroutes home-routes`の中に以下を追記する。

```:clj
  (POST "/sample" [text1 value1] (println text1 ":" value1) (edn {:val (str text1 "#" value1)}))
```

core.cljsからのリクエストを処理して返している。
レスポンスは（cljs-ajaxのデフォルトでは）ednで返す必要があるっぽい。

## 動作確認

`lein cljsbuild auto`を別窓で実行してClojureScriptの自動コンパイルをしておく。
`lein ring server`を実行するとサーバが起動して、（うまくいけば）ブラウザが起動して画面表示される。

# さいごに

あとは、上で編集したcore.cljs, home.html, home.cljを主に編集すればいい。
画面はhttp://greenapple-room.com/conc/user/TwitterBootstrap/bootstrap.html などを参考に

ClojureとClojureScriptのコードは自動的にコンパイルされるので楽～
ちなみにコンパイルされたClojureScriptはresources/public/js/out/にあるので困ったらこの中を覗くといい。

実行可能なjarの作成は`lein ring uberjar`でできる。（ポート番号の指定はPORT環境変数とかでできる）

まだ試してないけど以下のライブラリを使うのもよさそう。

```:clj
   [edn-config "0.2"]
   [yesql "0.4.0"]
   [domina "1.0.2"]
```