Help us understand the problem. What is going on with this article?

ClojureScriptでReact 2019

こんにちは。

普段はClojureとClojureScriptだけ書いていてJavaScriptは書かないのですが、いつもより広い範囲のオーディエンスにClojureの良さを語りたくなったので参加させていただきました。

この記事ではshadow-cljsというClojureScript用のツールによって

  • node&jvmさえあればClojureScriptでの開発を始められる
  • 既存のnodeモジュールを簡単に利用できる
  • => ClojureScriptでReactプロジェクト作るのめっちゃ楽しい!

という点を今回作った小さなプロジェクトを添えて主張しようと思います。

ClojureScriptとは

狭義のClojureはRich Hickeyが作ったJVM上で動く言語です。概要は @223kazuki さんの書いたキメるClojure高速開発がオススメです。

そのヤバめな言語であるClojureをソースとして読み、JavaScriptを吐き出すコンパイラがClojureScriptです。言語の特徴以外ではGoogle Closure Compilerに依存しており、プロダクションビルドの際にその圧縮力の恩恵を受けることが期待できる点がアピールポイントです。

(ClojureとClosureで名前が衝突する点もよく話題に上がります。)

開発環境事情

ClojureScriptは良い物だとして、素のClojureScriptコンパイラにはいくつか課題があります。

  • ClojureScriptコンパイラ自体はClojureライブラリ => Clojureを動かす環境のインストールが必要
  • ホットリローディングが無い
  • nodeモジュールを使うのが煩雑
    • + Google Closure Compilerによって行なわれる変数リネームによってプロダクションビルドで壊れがち

この辺りをナイスにケアしてくれるshadow-cljsというツールが数年前に登場し、nodeとJavaランタイムさえあればClojureScriptを始められる時代が来ています。

shadow-cljsを使う

shadow-cljs自体はnpmでインストールできるcliなので使い始める敷居が低いのが特徴です。

インストール

前提となるnodeとjvmがインストール済みの前提でそこら辺のライブラリと同じようにpackage.jsonに足すなりnpm installするなりするだけ!

shadow-cljs.edn

各ビルドの設定やClojureScriptの依存ライブラリを書くファイルです。

開発ビルド

npx shadow-cljs watch <build-name> とshellに打つとコンパイルされ、開発用のwebサーバーが起動します。この状態ではソースの変更が監視されており、cljsのソースを触る度に最新のコードがブラウザにwebsocketで配信されます。最新の動作を確認するためにブラウザの更新ボタンを押す必要がない幸せを得る機能がデフォルトで付属しているのは嬉しいポイント。

React/node moduleでデモ

今回はボタンを押すとnodeが追加、node間をドラッグするとedgeが追加される物をvis-networkとReagentというReactラッパーで作りました。

image.png

コードはこちら

(ns my.dev
  (:require
   [reagent.core :as reagent]
   ["vis-network" :as vis]))

(defn graph [{:keys [nodes edges
                     on-edge-add
                     add-edge-mode]}]
  [:div
   {:ref (fn [dom]
           (when dom
             (let [parent-dom (.-parentElement dom)
                   nw (vis/Network.
                       dom
                       #js {:nodes (vis/DataSet. (clj->js nodes))
                            :edges (vis/DataSet. (clj->js edges))}
                       (clj->js
                        {:layout {:randomSeed 111} ;;Make deterministic
                         :edges {:arrows "to"
                                 :color "red"
                                 :physics false}
                         :manipulation
                         {:addEdge (fn [data callback]
                                     (on-edge-add {:from (.-from data)
                                                   :to (.-to data)})
                                     (callback data))}}))]
               (when add-edge-mode
                 (.addEdgeMode nw))
               (doto nw
                 (.setSize
                  (.-clientWidth parent-dom)
                  (.-clientHeight parent-dom))
                 (.fit (clj->js (map :id nodes)))))))}])

(defn view []
  (reagent/with-let
    [state (reagent/atom {})]
    [:div
     [:button
      {:on-click #(swap! state
                         update
                         :nodes
                         conj
                         {:id (count (:nodes @state))
                          :label (str (count (:nodes @state)))})}
      "Add Node"]
     [graph {:nodes (:nodes @state)
             :edges (:edges @state)
             :add-edge-mode true
             :on-edge-add (fn [edge]
                            (swap! state update :edges conj edge))}]]))

(defn render-view []
  (reagent/render [view]
                  (js/document.getElementById "root")))

(defn ^:dev/after-load start []
  (js/console.log "start")
  (render-view))

(defn ^:export init []
  ;; init is called ONCE when the page loads
  ;; this is called in the index.html and must be exported
  ;; so it is available even in :advanced release builds
  (js/console.log "init")
  (render-view))

;; this is called before any code is reloaded
(defn ^:dev/before-load stop []
  (js/console.log "stop"))

細かい解説は需要があれば足しますが、ポイントは

  • nodeモジュールが特別なことをしなくても使える
  • reagentというReactラッパーが広く使われている
  • ホットリローディングがデフォルト

という点です。

もしClojure/ClojureScriptに興味を持っていただいた方は、twitterでつぶやくと捕捉されやすいです。あとはdosync radioというClojureの日本語ポッドキャストを今年から始めているので聴いてみてください。では良いお年を!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした