ClojureでWebアプリケーション開発 ~セットアップ~

ぼくは普段、RubyやPHPでWebアプリケーション開発を行っているのですが、以前から興味があってかじっていたClojureでもWebアプリケーション開発を行いたいと思っていたので今回その準備を行ったメモを共有したいと思います。

# フレームワークにLuminusを使う
普段はRailsやCakePHPなどフルスタックフレームワークを使うことが多いのですが、関数型言語の場合は小さなライブラリを組み合わせてシステムを作るのがあっていると思っていました。
ただ、1からライブラリを探すのも面倒なので、ある程度標準装備としてWebアプリケーションで使われるライブラリがパッケージングされていて、なおかつ後で組み合わせを変更するのが簡単そうなLuminusを使うことにしました。

下記のコマンドでleiningenのLuminusテンプレートを使ってプロジェクトを作成します。

````
$ lein new luminus my-app
````

参考URL
http://www.luminusweb.net/

# Sassを使う
今どきのWeb開発で生のCSSを書くのはやっぱり辛いですよね〜。

普段のWeb開発ではRailsならAssetsPipeline、その他のときにはCompassやgulpなどでSassをコンパイルしてcssを書いています。

Clojureでの開発でももちろんSassを使いたいということで、[lein-haml-sass](https://github.com/rtircher/lein-haml-sass)というleiningenのプラグインを使います。

インストールするには、project.cljの:pluginsセクションにlein-haml-sassを以下のように追加します。

````clj:project.clj
(defproject example "1.2.3"
  :plugins [[lein-haml-sass "0.2.7-SNAPSHOT"]])

````

そして以下のコマンドを実行してインストールします。

````
$ lein deps
````

lein-haml-sassはその名の通りhaml,sass,scssのコンパイルが出来るのですが、今回はsassのみで良いので、sassのコンパイルを行う設定を行います。

````clj:project.clj
(defproject example "1.2.3"
  :plugins [[lein-haml-sass "0.2.7-SNAPSHOT"]]
  :sass {:src "resources/sass"
         :output-directory "resources/public/css"
         :output-extension "css"})

````

設定をした後に以下のコマンドを実行すると、自動で:srcで指定したディレクトリに作成・更新されたsassファイルが、:output-directoryに指定したディレクトリにcssファイルにコンパイルされます。

````
$ lein sass auto
````

参考URL
https://github.com/rtircher/lein-haml-sass

# ClojureScriptを使う
せっかくClojureを使うならフロントエンドもJSじゃなくClojureScriptを使おうよ！ということで導入します。
個人的に、業務でのチーム開発を行う場合はフロントエンド開発者との連携のしやすさからClojureScript使う機会はないのでは？とも思いますが今回はお試しということで使ってみます。

ClojureScriptのコンパイルを行うために[lein-cljsbuild](https://github.com/emezeske/lein-cljsbuild)というleiningenプラグインを使います。
lein-cljsbuildをインストールするために以下のようにproject.cljに追記して下さい。

````clj:project.clj
:plugins [[lein-haml-sass "0.2.7-SNAPSHOT"]
          [lein-cljsbuild "1.0.3"]]

````

また、ClojureScriptへの依存関係を解決するために:dependenciesセクションに以下のように記述を追記して下さい。

````clj:project.clj
:dependencies [[org.clojure/clojurescript "0.0-2371"]]
````

上記の設定を行ったら以下のコマンドでインストールします。

````
$ lein deps
````

インストールが済んだらcljsbuildの設定を以下のようにproject.cljに追記していきます。

````clj:project.clj
  :cljsbuild {:builds [{:source-paths ["src-cljs"]
                        :compiler {:output-to "resources/public/js/main.js"
                                   :optimizations :whitespace
                                   :pretty-print true}}]})

````

設定を追記後に以下のコマンドを実行すると:source-pathsで指定したディレクトリ以下に置かれたcljsファイルを:output-toで指定したディレクトリにコンパイルされて出力されます。

````
$ lein cljsbuild auto
````

参考URL
https://github.com/clojure/clojurescript
https://github.com/emezeske/lein-cljsbuild

# データストレージにRedisを使う。
みんな大好きNoSQLっていうことで、Redisを使いたいと思います。
ClojureからRedisを扱うために[carmine](https://github.com/ptaoussanis/carmine)というライブラリを使います。

ライブラリをインストールする前にRedisをローカルマシンにインストールしておいて下さい。Macであれば、homebrewでインストールすることが出来ます。

````
$ brew install redis
````

インストールしたらredis-serverを起動させておいて下さい。
本来はdaemonにして使いますが、今回はとりあえず動作確認のために普通に起動します。

````
$ redis-server
````

project.cljの:dependenciesセクションに以下を追記してlein depsコマンドを実行します。

````clj:project.clj
:dependencies [[com.taoensso/carmine "2.8.0"]]

````

````
$ lein deps
````

実際にcarmineが使えるかどうか、replを起動して確認してみます。

````
$ lein repl
2.1.0
nREPL server started on port 54758 on host 127.0.0.1 - nrepl://127.0.0.1:54758
REPL-y 0.3.2, nREPL 0.2.3
Clojure 1.6.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_20-b26
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

my-app.repl=> (require '[taoensso.carmine :as car :refer (wcar)])

CompilerException java.lang.RuntimeException: No such var: encore/kw-identical?, compiling:(taoensso/carmine/protocol.clj:256:3)
````

エラーが発生した。。。


調べてみるとちょうど解決されている[Issue](https://github.com/ptaoussanis/carmine/issues/117)が見つかりました。

どうやら依存している[taoensso/encore](https://github.com/ptaoussanis/encore)というライブラリのバージョンが古いようなので、project.cljに最新のencoreを依存として記述します。

````clj:project.clj
:dependencies [[com.taoensso/carmine "2.8.0"]
               [com.taoensso/encore "1.18.1"]]
````
````
$ lein deps
````

依存関係が解決できたら、もう一度replで試してみます。

````
$ lein repl
my-app.repl=> (require '[taoensso.carmine :as car :refer (wcar)])
nil
my-app.repl=> (def server1-conn {:pool {} :sepc {:host "127.0.0.1" :port 6379}})  
#'my-app.repl/server1-conn
my-app.repl=> (defmacro wcar* [& body] `(car/wcar server1-conn ~@body))
#'my-app.repl/wcar*
my-app.repl=> (wcar* (car/ping))
"PONG"
my-app.repl=> (wcar* (car/set "myname" "hogehoge"))
"OK"
my-app.repl=> (wcar* (car/get "myname"))
"hogehoge"

````

上手くRedisと繋がりました！

参考URL
https://github.com/ptaoussanis/carmine
https://github.com/ptaoussanis/carmine/issues/117
https://github.com/ptaoussanis/encore
http://asy524.hatenablog.com/entry/2013/09/30/234635

# おわりに
とりあえず、ぼくがClojureでWebアプリケーション開発を始める上で最低限必要な準備は出来ました^^; 
これから開発を進めてみて他の言語に比べてClojureが何に適しているのかが実践から学んでいけたらなと思います。