Arantium Maestum

プログラミング、囲碁、読書の話題

Clojure Web Development勉強 - Clojurescript(その1)cljs.jarでコンパイル

一旦サーバサイドを離れて、フロントエンドの開発を進めてみる。

フロントエンドについては以前から少し試していて、拙いながらも渋谷のLisp.Meetupでもライブコーディングしながらプレゼンしたことがある。その時はClojurescriptからFigwheel、Reagent、d3.jsなどと結構いろんな部分に言及できた(その分話が散漫になったきらいはあるが・・・)。

初心に戻ってもう一度簡単なところから調べていきたい。

というわけで、生のclojurescriptをコンパイルするところから。

ClojureScript - Quick Start

公式サイトの上記のドキュメントをタネに、最低限のClojurescriptを書いてコンパイルして表示してみる。

そのコードというのはこれ:

(ns manual_clojurescript.core)
(js/alert "Hello Clojurescript!")

名前空間の定義と、ブラウザのアラート機能で"Hello Clojurescript!"と表示させるだけ。js/alertはClojurescriptからJavaScriptの機能を呼び出している。とりあえずこれをcore.cljsとしておく。Clojurescriptなので.cljsである。(cljcの話は違う記事で言及する)

さて、コードを書いたはいいが、これをどうすればいいのか。以下の三つのステップが必要になる。

  1. ClojurescriptをJavaScriptコンパイル
  2. JavaScriptをロードするHTMLドキュメントを作成
  3. HTMLドキュメントをブラウザで表示

そのために幾つかサポートのためのファイルとディレクトリ構成を設定する。最終的に以下のような構成になる。

.
├── build.clj
├── cljs.jar
├── index.html
└── src
    └── manual_clojurescript
        └── core.cljs

core.cljsがsrc/manual_clojurescript/のディレクトリの下にあるに注意。それ以外のファイルは全てディレクトリのトップレベルにある。

ClojurescriptをJavaScriptコンパイル

さて、まずステップ1のために必要なcljs.jarとbuild.cljについて。

cljs.jarはQuick Startに載っているリンクから落とせる、Javaで書かれているClojurescript->Javascriptコンパイラである。

そのコンパイラに出す指示を入れたファイルがbuild.cljで、内容は以下のようになっている。

(require 'cljs.build.api)
(cljs.build.api/build "src" {:output-to "out/main.js"})

srcディレクトリに含まれているcljsファイルをJSにコンパイルして、まだ未作成のoutディレクトリのmain.jsファイルに出力してくれ、という内容。

src/manual_clojurescript/core.cljs、build.cljそしてcljs.jarの三つが揃えばステップ1のコンパイルができる。bashから

java -cp cljs.jar:src clojure.main build.clj

で、outというディレクトリにmain.jsやその他もろもろが作成されるはずだ。構成としてはこんな感じ:

.
├── build.clj
├── cljs.jar
├── index.html
├── out
│   ├── cljs
│   │   ├── core.cljs
│   │   ├── core.js
│   │   └── core.js.map
│   ├── goog
│   │   ├── array
│   │   │   └── array.js
│   │   ├── asserts
│   │   │   └── asserts.js
│   │   ├── base.js
│   │   ├── debug
│   │   │   └── error.js
│   │   ├── deps.js
│   │   ├── dom
│   │   │   └── nodetype.js
│   │   ├── math
│   │   │   ├── integer.js
│   │   │   └── long.js
│   │   ├── object
│   │   │   └── object.js
│   │   ├── reflect
│   │   │   └── reflect.js
│   │   └── string
│   │       ├── string.js
│   │       └── stringbuffer.js
│   ├── main.js
│   └── manual_clojurescript
│       ├── core.cljs
│       ├── core.cljs.cache.json
│       ├── core.js
│       └── core.js.map
└── src
    └── manual_clojurescript
        └── core.cljs

outに見えるファイルの概要は以下のとおり:

  1. manual_clojurescriptディレクトリ:srcに含まれていた自前のclojurescriptコードのコンパイル
  2. cljsディレクトリ:clojurescript自体の言語機能やライブラリが含まれている
  3. googディレクトリ:Clojurescriptが乗っかっているGoogleオープンソースJavaScriptライブラリであるGoogle Clojure Libraryの出力先
  4. main.js:上記のディレクトリに含まれているJSをつなぎ合わせるコード

JavaScriptをロードするHTMLドキュメントを作成

さて、次はこのコンパイルされたJavaScriptのロード先であるHTMLドキュメント、index.htmlを作成する。今回は最低限ということで以下のようなファイルになる:

<html>
    <body>
        <script type="text/javascript" src="./out/goog/base.js"></script>
        <script type="text/javascript" src="./out/main.js"></script>
        <script type="text/javascript">goog.require("manual_clojurescript.core");</script>
    </body>
</html>

まずGoogle Closure Libraryの便利機能を裏で色々使うので、それをgoog/base.jsを通じてロードしておく。

次に自分の書いたコードも呼び出せるようmain.jsをロード。

最後に、Google Closure Libraryのgoog.requireを使って自分の書いたClojurescriptのコンパイル先であるmanual_clojure.coreを実行。これで、core.cljsに記述したロジックに従って処理が行われる。

HTMLドキュメントをブラウザで表示

それでは実際に走らせてみる。

一番手軽なのはbashから

open ./index.html

でローカルファイルとして開いてしまうこと。これでちゃんとアラートポップアップに"Hello Clojurescript!"と表示されるはず。

もうちょっとちゃんとローカルサーバ立ててみたい場合は:

python -m http.server

あるいは

python -m SimpleHTTPServer

(前者はPython 3.x、後者はPython 2.xの場合)

のようにサーバ立ててブラウザでlocalhost:8000などと見てもオッケー。

とりあえず最低限のClojurescriptを書いてコンパイルしてロードするHTML用意して開くところまでは来れた。次はlein-cljsbuildを使ったコンパイルプロセスの簡略化と自動化。