ClojureScript

Webpackを使ったClojureScript

このガイドは、ClojureScript 1.10.741以降を必要とし、クイックスタートへの familiarity を前提としています。.

このページでは、Webpackなどの一般的なJavaScriptバンドラーにClojureScriptを統合する方法について説明します。Node.jsがインストールされている必要があります。このガイドは、クイックスタートを読了済みであることを前提としています。このガイドは、Webpack 2に関する優れたガイドから自由に借用しています。

ここではWebpackを使用していますが、これらの手順は、React Native用のMetroなどの他のバンドラーにも簡単に適用できます。

プロジェクトの設定

最初にプロジェクトディレクトリを作成します。

mkdir hello-bundler
cd hello-bundler

次の内容を含むdeps.ednファイルを作成します。

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

空のpackage.jsonファイルを作成します。

echo "{}" > package.json

Webpackとそのコマンドラインツールを追加します。

npm install --save-dev webpack webpack-cli

これで、JSの依存関係を設定する準備ができました。

JavaScript依存関係

reactとreact-domをインストールします。

npm install --save react react-dom

次に、次の内容を含むsrc/hello_bundler/core.cljsを作成します。

(ns hello-bundler.core
  (:require [react]))

(.log js/console react/Component)

通常のrequireと通常の名前空間のようにReactをrequireしていることに注意してください。

これを動作させるには、いくつかのコンパイラオプションを設定する必要があります。次の内容を含むbuild.ednファイルを作成します。

{:main hello-bundler.core
 :output-to "out/index.js"
 :output-dir "out"
 :target :bundle
 :bundle-cmd {:none ["npx" "webpack" "./out/index.js" "-o" "out" "--mode=development"]
              :default ["npx" "webpack" "./out/index.js" "-o" "out"]}
 :closure-defines {cljs.core/*global* "window"}} ;; needed for advanced

ビルドによってout/index.jsが生成されます。これは、Webpackが探しているエントリファイルです。バンドラーの結果を出力ディレクトリに書き戻します。

新しい:target :bundleオプションに注目してください。これは、生成されたコードが、Node.jsスタイルのrequireを処理できる一般的なJavaScriptバンドラーと互換性があることを保証します。また、エクスターン推論など、他の多くの適切なデフォルト設定も設定されるため、高度なコンパイルが機能します。:bundle-cmdは、ClojureScriptビルドの完了後に実行する任意のシェルコマンドです。Metroのような監視バンドラーの場合は、:bundle-cmdは不要です。

実際に見てみましょう。次のコマンドを実行すると、プロジェクトがビルドされ、REPLが起動します。

clj -M -m cljs.main -co build.edn -v -c -r

デフォルトのブラウザでhttps://:9000が開きます。開発者コンソールを開くと、React.Componentがログ出力されていることがわかります。

REPLでは、reactをrequireして、それとかかわることができます。

user> (require 'react)

外部ライブラリのオーバーライド

最新のバンドル版がまだCLJSJSに表示されていないため、node_modulesからReactを使用したい場合があります。それでも、ReagentのようなClojureScript Reactバインディングを使用したい場合があります。ClojureScriptはこれをすぐにサポートしています。

これを示すために、deps.ednを次のように変更します。

{:deps {org.clojure/clojurescript {:mvn/version "1.10.741"}
        reagent {:mvn/version "0.10.0" :exclusions [cljsjs/react cljsjs/react-dom]}}}

ソースファイルを次のように変更します。

(ns hello-bundler.core
  (:require [goog.dom :as gdom]
            [reagent.dom :as dom]))

(defn simple-component []
  [:div
   [:p "I am a component!"]
   [:p.someclass
    "I have " [:strong "bold"]
    [:span {:style {:color "red"}} " and red "] "text."]])

(dom/render [simple-component] (gdom/getElement "app"))

プロジェクトを再構築し、REPLを実行します。

clj -M -m cljs.main -co build.edn -v -c -r

エクスターン推論により高度なコンパイルが機能することを確認するために、高度なビルドを作成してみましょう。REPLは高度なコンパイル下では機能しないため、https://:9000を手動で開く必要があります。

clj -M -m cljs.main -co build.edn -O advanced -v -c -s

以上です!

Web Workerの構築

:target :bundleでWeb Workerをビルドする場合、Webpack(または好みのバンドラー)を使用してWeb Workerブートストラップを追加します。

そのため、ビルドの:targetは引き続き:bundle:webworkerではありません)になりますが、バンドラーにWeb Workerをビルドするように指示します。たとえば、Webpackでは、:bundle-cmdエントリに--target=webworker引数を追加します。

また、ブラウザビルドでは"window"であるのに対し、cljs.core/global"self"として定義する必要があります。

build-webworker.ednの例を以下に示します。

{:main hello-bundler.webworker
 :output-to "out/worker/index.js"
 :output-dir "out/worker"
 :target :bundle
 :bundle-cmd {:none ["npx" "webpack" "out/worker/index.js" "-o" "out/worker/main.js" "--target=webworker" "--mode=development"]
              :default ["npx" "webpack" "out/worker/index.js" "-o" "out/worker/main.js" "--target=webworker"]}
 :closure-defines {cljs.core/*global* "self"}} ;; needed for advanced

元の作者:David Nolen