mkdir -p hello-modules
cd hello-modules
mkdir src
本指南需要 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
點擊按鈕。您將會看到 :bar
模組被載入,並且另一個命名空間中的函數被調用。
建置您的專案
clj -M -m cljs.main -co build.edn -O advanced -c -s
導覽至 https://127.0.0.1:9000/index.html。您的應用程式即使經過進階編譯也應該能正常運作。
變更 foo.core
以採用像 cljs.reader
的新 require。重新建置。
您應該會看到 cljs.reader
被移動到 :foo
模組,但不會移動到 :bar
。
如果您檢查 out
中的分割檔案,您會看到 foo.js
比 bar.js
大。
由於分割中的程式碼是在 JavaScript 的全域範圍中執行的,有時它可能會干擾同一頁面上載入的其他 JavaScript(例如,分析),這可能會導致不可預測的行為。如果這對您的應用程式來說是一個問題,請透過指定 :rename-prefix
編譯器選項來為產生的 JavaScript 中的所有變數加上前綴。
原始作者:David Nolen