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

需要注意的一件重要事情是,所谓的 main 选项,如 --compile--main--repl 必须始终放在最后。

生产环境构建

您可能已经注意到 out 目录,其中包含所有已编译的 JavaScript 代码。这里大约有 6.5 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。如果您压缩此文件,您会发现它约为 20K。这比 jQuery 依赖项小得多,但是当使用 ClojureScript 时,您隐式依赖于整个 ClojureScript 标准库 (10KLOC) 和 Google Closure 库 (300KLOC)。您可以感谢死代码消除。

您可以通过运行内置的简单 Web 服务器(通过 --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! 打印。内置 Web 服务器会压缩 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