Quick Start

macOSまたはLinuxを使用している場合、このチュートリアルの主要部分に必要な唯一の依存関係は、WebブラウザとClojureのインストールです。Windowsの場合は、Java 8とスタンドアロンのClojureScript JARが必要です。なお、ウェブブラウザの要件はヘッドレス環境を除いたものであり、このチュートリアルのNode.jsの部分に目を通すことをお勧めします。

こんにちは、ClojureScript

このチュートリアルでは、簡単なClojureScriptプロジェクトのコンパイルと実行、およびコードをインタラクティブに開発およびテストするためのREPLの実行について説明します。このチュートリアルでは、コマンドラインに関する基本的な知識を前提としています。

まず、Hello Worldプログラム用のプロジェクトフォルダを作成します。必要なファイルとフォルダのリストは以下のとおりです。ディレクトリ構造と名前のアンダースコアは重要なので、変更しないようにしてください。

hello-world        # Our project folder
├─ src             # The CLJS source code for our project
│  └─ hello_world  # Our hello_world namespace folder
│     └─ core.cljs # Our main file
├─ cljs.jar        # (Windows only) The standalone Jar you downloaded earlier
└─ deps.edn        # (macOS/Linux only) A file for listing our dependencies

macOSまたはLinuxをお使いの場合、deps.ednファイルには以下の内容が含まれています。

{:deps {org.clojure/clojurescript {:mvn/version "1.10.758"}}}

お好きなテキストエディターで、src/hello_world/core.cljsを以下のように編集してください。

(ns hello-world.core)

(println "Hello world!")

さて、簡単なプログラムができたので、ClojureScriptをビルドして実行してみましょう。hello-worldのプロジェクトディレクトリにいることを確認し、以下のコマンドを実行します。

clj -M --main cljs.main --compile hello-world.core --repl

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --compile hello-world.core --repl

デフォルトのWebブラウザでは、以下のようなページが表示されます。

browse01

Linuxをお使いの方でREPLが起動しない場合は、ブラウザの自動起動を無効にして、手動で http://localhost:9000 を開いてみてください。

clj -M --main cljs.main --repl-opts "{:launch-browser false}" --compile hello-world.core --repl

数秒後、ターミナルにHello world! が表示され、REPLのプロンプトが表示されます。以下のような式を評価してみてください。

(inc 1)
(map inc [1 2 3])
(.getElementById js/document "app")

ここで使われているフラグをもう少し詳しく見てみましょう。--main は Clojure の関数、ここでは cljs.main を起動します。cljs.main関数は、一般的なタスクを指定するための様々なコマンドライン引数をサポートしています。ここでは--compileを使ってhello-world.core名前空間をコンパイルすることを指定しています。これに続く --repl は、コンパイルが完了したときにすぐに REPL を起動したいことを示します。

src/hello_world/core.cljsのソースファイルを以下のように変更します。

(ns hello-world.core)

(println "Hello world!")

;; ADDED
(defn average [a b]
  (/ (+ a b) 2.0))

REPLのプロンプトで、次のように評価して、ネームスペースを再コンパイルし、再読み込みします。

(require '[hello-world.core :as hello] :reload)
(hello/average 20 13)

結果は16.5となるはずです。

間違いを犯してみましょう。(ffirst [1])を評価してみてください。JavaScriptではなくClojureScriptのソースロケーションを指す、ソースマップされたスタックトレースが得られるはずです。これは、デバッグをより良いものにします。

ClojureScriptコンパイラが提供するオプションは、--helpを使うと簡単に調べることができます。これまでに使用したすべてのオプションの省略されたフラグがあることがわかります。

clj -M -m cljs.main --help

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --help

注意点としては、--compile, --main, --replなどのいわゆるメインオプションは、常に最後に来なければならないということです。

プロダクション・ビルド

コンパイルされたすべてのJavaScriptが格納されているoutディレクトリにお気づきでしょうか。約6.5メガバイト分のJavaScriptが入っています。これは扱いにくいと思われるかもしれませんが、幸いなことに、ClojureScriptコンパイラはGoogle Closure Compiler用に最適化された出力を生成します。Google Closure Compilerは多くの最適化を行いますが、ブラウザベースのクライアントにとって最も重要なのは、ミニマイズとデッドコードの除去です。

先ほど行ったREPLの修正をsrc/hello_world/core.cljsから削除してみましょう。

(ns hello-world.core)

(println "Hello world!")

--optimizationsフラグに適切な値を設定することで、リリースビルドを作成することができます。デフォルトの最適化レベルはnoneですが、今回はClojureScriptとGoogle Closure Compilerの両方が提供する最適化をすべて使用したいので、advancedを指定します。--optimizationsの他の有効なオプションはwhitespacesimpleですが、これらはあまり使われません。

clj -M -m cljs.main --optimizations advanced -c hello-world.core

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --optimizations advanced -c hello-world.core

このプロセスにはかなりの時間がかかるため、このコンパイルモードは開発には使用しません。

out/main.jsを見ると、ファイルサイズは約90Kになっているはずです。このファイルをzip形式で圧縮すると、約20Kになります。これは、jQueryの依存関係よりもはるかに小さいのですが、ClojureScriptを使用すると、ClojureScript標準ライブラリ全体(10KLOC)とGoogle Closure Library(300KLOC)への暗黙の依存関係があります。これは、デッドコードの排除に起因するものです。

このファイルがまだ動作するかどうかは、-serve フラグを使って内蔵のシンプルなウェブサーバを実行することでテストできます。

clj -M -m cljs.main --serve

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --serve

このコマンドはREPLを起動しないので,ブラウザ・ウィンドウは自動的には開かれません。お好きなブラウザで http://localhost:9000 にアクセスしてください。JavaScriptコンソールを確認すると、Hello world! と表示されているはずです。内蔵のウェブサーバは、JavaScriptコンテンツをgzip圧縮します。ブラウザのJavaScript ConsoleのNetworkタブを確認すると、JavaScriptの総ペイロードが20K程度になっていることが確認できるはずです。

Node.jsでのClojureScriptの実行

まず、Node.jsがインストールされていることを確認してください。Node.jsのインストール方法については、Node.js wikiを参照してください。現時点では、Node.jsの現在の安定版(>= 0.12.X)のみがサポートされています。

先に進む前に、ソースマッピングを有効にします。

npm install source-map-support

それでは、Nodeプロジェクトをビルドしてみましょう。特定のJavaScriptターゲット用のコードを生成することを--targetで指定できます。--targetフラグが与えられない場合、ClojureScriptはブラウザ用のコードを生成します。また、ここでは --output-to を使って --output-to ファイルを指定しています。

clj -M -m cljs.main --target node --output-to main.js -c hello-world.core

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --target node --output-to main.js -c hello-world.core

以下のようにしてファイルを実行することができます。

node main.js

注:Node.jsでは、高度な最適化を使う理由はほとんどありません。高度な最適化はパフォーマンスに関連する最適化を行いますが、V8、SpiderMonkey、JavaScriptCoreなどの最新のJavaScript仮想マシンに搭載されている最適化によって、これらの最適化はほとんど必要なくなりました。Node.jsでは、simpleまたはnoneによる最適化で十分です。

Node.js REPL

Node.jsのREPLの実行は、ブラウザのREPLの実行と似ています。異なるJavaScript評価環境を使用するREPLを指定するには、--repl-envを指定します。この値のデフォルトはブラウザのREPLですが、今回はnodeを指定したいと思います。

clj -M -m cljs.main --repl-env node

Windowsの場合は、

java -cp "cljs.jar;src" cljs.main --repl-env node

これまでに説明したブラウザ用のREPLインタラクションはすべて動作するはずです。

依存関係

ClojureScriptは、ClojureScriptとJavaScriptの依存関係を含めるためのさまざまなオプションをサポートしています(詳細はDependenciesを参照)。

Reactは、ClojureScriptプロジェクトでよく使われる依存関係です。CLJSJSバンドルされたバージョンを提供しています。それをインクルードする方法を見てみましょう。

deps.ednファイルを修正します。

{:deps {org.clojure/clojurescript {:mvn/version "1.10.758"}
        cljsjs/react-dom {:mvn/version "16.2.0-3"}}}

簡単なプログラムを以下のように編集して、Reactがきちんとrequireされるようにしましょう。

(ns hello-world.core
  (:require react-dom))

(.render js/ReactDOM
  (.createElement js/React "h2" nil "Hello, React!")
  (.getElementById js/document "app"))

ビルドと実行をしましょう。

clj -M -m cljs.main -c hello-world.core -r

ブラウザが起動すると、一瞬デフォルトのページが表示されますが、すぐにHello React!と書かれたh2タグで置き換えられます。

原著者 デビッド・ノレン

www.DeepL.com/Translator(無料版)で翻訳しました。