Arantium Maestum

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

Clojure Web Development勉強 - FigwheelでCSS Auto-Loading

Single Page Applicationで複雑かつ洗練されたGUIを実装するためには、一般的にHTMLで定義されている文書のコンテンツだけではなく、CSSで定義されているスタイルをどうコントロールするかも非常に重要なポイントになる。

JavaScriptで直接DOMにコンポーネントごとのスタイルを挿入することも可能なのだが、Reactの実例を見るとどちらかというとCSSは別途用意することの方が多いようである。コンポーネントのclassやid指定でCSSと紐付ける形になる。公式チュートリアルもこの方式を採っていた。

別にCSSファイルを用意するのはいいのだが、CSSの変更は普通HTMLをリロードしないと反映されない。せっかくFigwheelでClojureScriptの変更を自動的かつ即座に反映させているのに、コンポーネントの見た目をいじってもリロードしないと変化が見えないというのは片手落ちである。

幸いFigwheelには特定のディレクトリのCSSをモニタして、変更があればWeb Socketでオートロードしてくれる設定があるので使ってみる。

ディレクトリ構造

とりあえずこんな感じのディレクトリ構造

.
├── project.clj
├── resources
│   └── public
│       ├── css
│       │   └── main.css
│       └── index.html
└── src
    └── min_css
        └── core.cljs

いつもの構成に加えてresources/public/cssにmain.cssを定義している。

HTML

もちろんHTML文書でこのmain.cssを指定している:

<html>
    <head>
        <link href="css/main.css" rel="stylesheet" type="text/css">
    </head>
    <body>
        <div id="app"></div>
        
        <script src="js/out/goog/base.js"></script>
        <script src="js/main.js"></script>
        <script>goog.require('min_css.core')</script>
    </body>
</html>

あとは今までどおりにreagent用のapp div作成とJavaScriptの呼び出し。

Reagentコンポーネント

core.cljsの中にあるReagentのmy-appコンポーネントで要素を三つ定義している:

(defn my-app []
  [:div
   [:h1 "Hello Reagent"]
   [:p "Some random text in a regular p tag"]
   [:p.my-class "More random text in a my-class p tag"]])

h1とただのpとp.my-classである。Reactチュートリアルでも見たように、Reagentでは:tag.xでxクラス属性を、:tag#yでyというidをDOM要素に付与できる。

CSS

body全体とこの三つの要素のスタイルをCSSで定義する:

body {
    background: #ddd;
}

h1 {
    color: #f00;
}

p {
    font: 18px "Century Gothic", Futura, sans-serif;
}

.my-class {
    font-size: 12px;
    background: #ddf;
}

見た目はひどいがまあサンプルだと思って・・・

Figwheel設定

あとはproject.cljでfigwheelにcssの在処を指定してオートロードするよう設定する:

(defproject min-css "0.0.1"
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.9.293"]
                 [reagent "0.6.0"]]

  :plugins [[lein-cljsbuild "1.1.4"]
            [lein-figwheel "0.5.7"]]

  :figwheel {:css-dirs ["resources/public/css"]} ;ここ

  :cljsbuild
  {:builds {:dev {:source-paths ["src"]
                  :figwheel true
                  :compiler {:output-to "resources/public/js/main.js"
                             :output-dir "resources/public/js/out/"
                             :optimizations :none}}}})

一行figwheelへの指示を追加するだけ。

実行

あとはlein figwheelで実行してブラウザでlocalhost:3449を開くだけ。

core.cljsもmain.cssも変更して保存した瞬間にブラウザで変更が反映される。

スタイルを動的に変更できるようになるのはけっこう快感。CSSシークレットみたいな本をいろいろとイジリ倒してみたくなる。

次はCSSの指定もednで!という業の深い話を。