ClojureScript

コード分割

このガイドでは、ClojureScript 1.10.238以降が必要であり、クイックスタートの内容を理解していることを前提としています。.

クライアントアプリケーションが大きくなるにつれて、特定の論理画面を実行するために実際に必要なコードのみを読み込むことが望ましくなります。以前は、ClojureScriptの:modulesコンパイラオプションでこのようなコード分割が可能でしたが、この機能は:advancedコンパイルでのみ機能し、ユーザーはこれらの分割の読み込みを管理する必要がありました。また、:modulesでは、最適な分割を行うために多くのエントリを手動で明示的に配置する必要がありました。そうでない場合、依存関係は:cljs-baseに移動されてしまいます。

これらの問題はすべて、ClojureScriptで直接対処されるようになりました。このガイドでは、簡単なプロジェクトのコード分割について説明し、これらの新しい拡張機能を紹介します。

簡単なプロジェクトを作成する

プロジェクトフォルダを作成します。

mkdir -p hello-modules
cd hello-modules
mkdir src

次のようなdeps.ednファイルを作成します。

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

次のようなbuild.ednファイルを作成します。

{:output-dir "out"
 :asset-path "/out"
 :browser-repl false
 :modules {:foo {:entries #{foo.core}
                 :output-to "out/foo.js"}
           :bar {:entries #{bar.core}
                 :output-to "out/bar.js"}}}

次に、index.htmlファイルを作成します。

<html>
    <body>
         <button id="button">Load Bar!</button>
         <script src="out/cljs_base.js" type="text/javascript"></script>
         <script src="out/foo.js" type="text/javascript"></script>
    </body>
</html>

ソース

foo.core名前空間を作成します。

mkdir -p src/foo
touch src/foo/core.cljs

このファイルを次のように編集します。

(ns foo.core
  (:require [goog.dom :as gdom]
            [goog.events :as events]
            [cljs.loader :as loader])
  (:import [goog.events EventType]))

(println "I'm foo!")

(events/listen (gdom/getElement "button") EventType.CLICK
  (fn [e]
    (loader/load :bar
      (fn []
        ((resolve 'bar.core/woz))))))

(loader/set-loaded! :foo)

見慣れない名前空間cljs.loaderに注目してください。この名前空間は、コード分割の読み込みを管理するためのGoogle Closure ModuleManagerシングルトンを提供します。このマネージャーは、:modulesで定義したモジュールグラフで初期化されます。

ユーザーがボタンをクリックすると、:barモジュールが読み込まれ、bar.core名前空間に存在する関数が呼び出されます。resolveを使用していることに注意してください。これは、必要のないものを直接呼び出すことができないためです。resolveなしでこれを行おうとすると、ClojureScriptコンパイラはコンパイル中に未宣言の変数警告を出力します。

最後に、cljs.loader/set-loaded!を使用してモジュールが読み込まれたことを手動でマークする必要があることに注意してください。これがなければ、依存関係が複数回読み込まれ、予期しない動作につながる可能性があります。

bar.core名前空間を作成します。

mkdir -p src/bar
touch src/bar/core.cljs
(ns bar.core
  (:require [cljs.loader :as loader]))

(println "I'm bar!")

(defn woz []
  (println "WOZ!"))

(loader/set-loaded! :bar)

プロジェクトをビルドする

プロジェクトをビルドし、組み込みHTTPサーバーを起動します。

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

https://:9000/index.htmlに移動します。

ボタンをクリックします。:barモジュールが読み込まれ、他の名前空間の関数が呼び出されることがわかります。

リリースビルド

プロジェクトをビルドします。

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

https://:9000/index.htmlに移動します。高度なコンパイルが行われていても、アプリケーションは正しく機能するはずです。

foo.corecljs.readerのような新しいrequireを受け入れるように変更します。再ビルドします。

cljs.reader:fooモジュールに移動されますが、:barには移動されないことがわかります。

outにある分割ファイルを確認すると、foo.jsbar.jsよりも大きいことがわかります。

追加の注意事項

分割されたコードはJavaScriptのグローバルスコープで実行されるため、同じページに読み込まれた他のJavaScript(例:アナリティクス)と干渉し、予期しない動作を引き起こす可能性があります。これがアプリケーションで問題になる場合は、:rename-prefixコンパイラオプションを指定して、生成されたJavaScriptのすべての変数にプレフィックスを付けます。

原著者:David Nolen