ClojureScript

快速入門

如果您使用 macOS 或 Linux,本教學主要部分所需的相依性只有網頁瀏覽器和 Clojure 的安裝。在 Windows 上,您需要 Java 8獨立的 ClojureScript JAR。請注意,網頁瀏覽器的需求排除了無頭環境,我們建議跳到本教學的 Node.js 部分。

Hello, 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.11.54"}}}

在您最喜歡的文字編輯器中編輯 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

您的預設網頁瀏覽器將開啟一個如下所示的頁面

Browser REPL Serving Default index.html

如果您執行的是 Linux 且 REPL 沒有啟動,請嘗試停用瀏覽器自動啟動並手動開啟 https://127.0.0.1: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.maincljs.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])。您應該會得到一個來源對應的堆疊追蹤,指向 ClojureScript 原始碼位置,而不是 JavaScript 位置。這使得除錯更加容易。

您可以使用 --help 輕鬆探索 ClojureScript 編譯器提供的選項。您將看到我們到目前為止使用的所有選項都有縮寫標誌。

clj -M -m cljs.main --help

在 Windows 上

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

一個重要的注意事項是,所謂的主要選項,例如 --compile--main--repl 必須永遠放在最後面。

產品建置

您可能已經注意到包含所有已編譯 JavaScript 的 out 目錄。其中大約有 6 又 1/2 MB 的 JavaScript。這看起來可能很笨重,但幸運的是,ClojureScript 編譯器產生的輸出針對 Google Closure Compiler 進行了最佳化。Google Closure Compiler 執行許多最佳化,對於基於瀏覽器的客戶端而言,最重要的最佳化是縮小和無效程式碼消除。

讓我們從 src/hello_world/core.cljs 中移除我們之前所做的 REPL 修改

(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 函式庫 (300KLOC)。您可以感謝無效程式碼消除。

您可以透過 --serve 標誌執行內建的簡單網頁伺服器來測試此檔案是否仍然有效

clj -M -m cljs.main --serve

在 Windows 上

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

此命令不會啟動 REPL,因此不會自動開啟瀏覽器視窗。使用您最喜歡的瀏覽器導覽至 https://127.0.0.1:9000。檢查 JavaScript 主控台,您應該看到印出的 Hello world!。內建的網頁伺服器會壓縮 JavaScript 內容。檢查您瀏覽器的 JavaScript 主控台網路標籤,您應該能夠確認總 JavaScript 負載現在約為 20K。

在 Node.js 上執行 ClojureScript

首先,請確定您已安裝 Node.js。如需有關安裝 Node.js 的指示,請參閱 Node.js wiki。目前僅支援 Node.js 的當前穩定版本 (>= 0.12.X)。

在我們繼續之前,請啟用來源對應

npm install source-map-support

讓我們建置您的 Node 專案。我們可以透過 --target 指定我們想要為特定的 JavaScript 目標產生程式碼。如果未提供 --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 下,幾乎沒有理由使用進階最佳化。雖然進階最佳化確實應用了與效能相關的最佳化,但這些最佳化現在很大程度上被現代 JavaScript 虛擬機器 (例如 V8、SpiderMonkey 和 JavaScriptCore) 中存在的最佳化所取代。對於 Node.js,simplenone 最佳化就足夠了。

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 相依性 (詳細資訊請參閱 相依性)。

React 是 ClojureScript 專案中常用的相依性。CLJSJS 提供了一個 捆綁版本。讓我們看看如何包含它。

修改您的 deps.edn 檔案

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

讓我們編輯我們的簡單程式,使其如下所示,以便正確地要求 React

(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 標籤取代。

原始作者:David Nolen