個人的に興味のある内容なので、自分の言葉でまとめます。
背景
clojureとはjavaの上で動くlisp系(関数型)言語です。clojurescript(以後cljs)とはjavascript(以後js)をclojureで書ける言語です。
cljsをjsに変換するにはjavaを必要とするleiningenなどのツールを使うことが多いですが、javaに頼らずとも変換できる仕組みがあるようです。
今回はその仕組みの1つであるlumoを利用して、nodejsのアプリをcljsで書いて動かしてみました。
全体像
この順に説明していきます。- 動作環境
- lumoのインストール
- lumo + replでhello world
- lumo + ファイルでhello world
- cljsをjsにビルドして、nodeコマンドでhello world
- lumo + express
- cljsをjsにビルドして、nodeコマンドでexpressを実行
- まとめ
- 参考
動作環境
Linux(ubuntu) + nodejs + npmで動作確認しました。$ node -v v8.4.0 $ npm -v 5.3.0
lumoのインストール
下記のコマンドでインストールします。sudo npm i -g lumo-cljs
しかし、バグが残っているようで、自分が試した時は下記のエラーが出てインストールできませんでした。
$ sudo npm install -g lumo-cljs /usr/local/bin/lumo -> /usr/local/lib/node_modules/lumo-cljs/bin/lumo.js > lumo-cljs@1.7.0 install /usr/local/lib/node_modules/lumo-cljs > node scripts/npm_install.js || nodejs scripts/npm_install.js internal/streams/legacy.js:59 throw er; // Unhandled stream error in pipe. ^ Error: EACCES: permission denied, open 'lumo_linux64.zip' sh: 1: nodejs: not found npm ERR! file sh npm ERR! code ELIFECYCLE npm ERR! errno ENOENT npm ERR! syscall spawn npm ERR! lumo-cljs@1.7.0 install: `node scripts/npm_install.js || nodejs scripts/npm_install.js` npm ERR! spawn ENOENT npm ERR! npm ERR! Failed at the lumo-cljs@1.7.0 install script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /home/asuki/.npm/_logs/2017-08-31T14_21_26_038Z-debug.log
上記のエラーが出た場合、「--unsafe-perm」というオプションを付けて、下記ようなコマンドを実行すればインストールできました。
sudo npm i -g lumo-cljs --unsafe-perm
インストールできたら、下記のコマンドでlumoのバージョンを確認できます。
lumo --version
自分が試した時は1.7.0でした。
lumo + replでhello world
replとは、対話型のインターフェース(プログラムを入力したら、それがすぐに実行される入力欄)です。下記のコマンドでreplを起動できます。
lumo -r
下記のコマンドでHello world.と出力できます。
(prn "Hello world.")
jsのconsole.logも使えます。
(js/console.log "Hello world")
exitでreplを終了できます。
exit
replでプログラムを実行できました。
「だから何なの?」と感じるかもしれませんが、「この処理は、こう書いたら動くかな?」など小さな単位で試行錯誤をするときに便利なことがあります。
lumo + ファイルでhello world
今度はファイルに処理を記述して、それを実行してみます。ファイルを管理するために、プロジェクトを作ります。
mkdir -p ~/gitprojects/lumo-practice cd gitprojects/lumo-practice npm init
ファイルを置くディレクトリを作ります。
cd gitprojects/lumo-practice mkdir src/hello_world
下記のcljsファイルを作ります。
src/hello_world/core.cljs
(ns hello-world.core) (defn greeting [] (js/console.log "Hello world.")) (defn -main [] (greeting))
下記のコマンドで実行できます。
lumo -c src -m hello-world.core
lumoコマンドでプログラムを実行できました。
cljsをjsにビルドして、nodeコマンドでhello world
ビルドの設定ファイルを作ります。ファイル名は「build.cljs」とかでも良いのですが、後で別のbuildファイルも書くので、「build_hello_world.cljs」というファイル名にしました。
src/build_hello_world.cljs
(require '[lumo.build.api :as b]) (b/build "src" {:main 'hello-world.core :output-to "index_hello_world.js" :optimizations :advanced :target :nodejs})
lumoのビルドはなぜかmainを認識してくれないので、下記のようにmainの指定をhello_world/core.cljsの末尾に追記します。
src/hello_world/core.cljs
(set! *main-cli-fn* -main)
下記のコマンドでビルドできます。
(環境によって、数十秒から数分かかります。)
lumo -c src build_hello_world.cljs
ビルドができたら下記のコマンドでjsファイルをnodeのプログラムとして実行できます。
node index_hello_world.js
動きました。
lumo + express
lumo環境下のcljsはnodejsのライブラリを利用できます。nodejsでwebシステムを作るのに利用できるexpressというライブラリをcljsで利用してみました。
expressをプロジェクトに追加します。
npm i express --save
express用のディレクトリを作ります。
mkdir src/express_sample
下記のプログラムを作成します。
src/express_sample/core.cljs
(ns express-sample.core) (def express (js/require "express")) (def app (express)) (.get app "/" (fn [req res] (.send res "Hello world. sample"))) (.get app "/sample" (fn [req res] (.send res "sample page home"))) (.listen app 3000 (fn [] (js/console.log "started-express")))
下記のコマンドでexpress-sample.coreを実行します。
lumo -c src -m express-sample.core
警告文は出ますが、動きました。
ブラウザで「http://localhost:3000」にアクセスすると「/」で定義したページが表示されます。
sampleのリンクをクリックすると、「/sample」のパスで定義したページも表示されます。
cljsでexpressを利用できました。
cljsをjsにbuildして、nodeコマンドでexpressを実行
expressを利用したcljsをビルドするために、下記のファイルを作成します。
src/build_hello_world.cljs
(require '[lumo.build.api :as b]) (b/build "src" {:main 'hello-world.core :output-to "index_hello_world.js" :optimizations :advanced :target :nodejs})
lumoのビルドはなぜかmainを認識してくれないので、下記のようにmainの指定をhello_world/core.cljsに追記します。
src/build_express_sample.cljs
(require '[lumo.build.api :as b]) (b/build "src" {:main 'express-sample.core :output-to "index_express_sample.js" :optimizations :simple :target :nodejs})
注意すべきなのは、optimizationsをsimpleにしているところです。
noneにするとビルドに失敗します。
advancedにすると、expressの関数名が置き換えられてしまって、期待通りに動きません。
下記のコマンドでビルドできます。
lumo -c src build_express_sample.cljs
ビルドできたら下記のコマンドでjsファイルをnodeのプログラムとして実行できます。
node index_express_sample.js
lumoのコマンドで実行した時のように「http://localhost:3000」にアクセスすると、ページを確認できます。
expressを利用したcljsをビルドして、nodeで実行できました。
まとめ
nodejsの環境下で、replの起動、cljsの実行、cljsをjsにビルド、することができました。これにより、javaに頼らずともlisp系の言語であるclojurescriptでnodejsアプリをれることが分かりました。
個人的に嬉しいです。
共有する内容は以上です。
lumoだけではcljsのライブラリを利用しにくかったので、calvinを使ってhiccup(html作成サポートのためのcljsライブラリ)を利用する記事も書きました。
よかったらこちらもどうぞ。
calvinを使ってhiccupを利用したnodejsアプリを作る方法
参考
lumoCompiling ClojureScript Projects Without the JVM
asukiaaa/bootstrapped-cljs-practice lumo-only
0 件のコメント :
コメントを投稿