如何将ClojureScript编译为Node.js?

9

为什么 cljsbuild 无法正确编译 gulpfile.js 文件?

这是我 project.clj 的配置:

(defproject cljs-selfstudy "0.1.0-SNAPSHOT"
  :description "Where I want to learn about clojurescript"
  :url "http://example.com"

  :dependencies [[org.clojure/clojure "1.7.0-alpha2"]
                 [org.clojure/clojurescript "0.0-2322"]]

  :plugins [[lein-cljsbuild "1.0.4-SNAPSHOT"]]

  :source-paths ["src"]


  :cljsbuild {
              :builds [{:id "gulpjs"
                        :source-paths ["src/gulpjs"]
                        :compiler {
                                   :output-to "gulpfile.js"                                   
                                   :optimizations :none
                                   :pretty-print true}}]})

这是我的core.cljs文件。
(ns gulpjs.core
  (:require [cljs.nodejs :as node]))

(def gulp (node/require "gulp"))

(def gulp-livereload (node/require "gulp-livereload"))

(def gulp-markdown (node/require "gulp-markdown"))

(def gulp-watch (node/require "gulp-watch"))

(.task gulp "markdown" 
       #(-> (.source gulp "../markdown-explained")
            (.pipe (gulp-markdown))
            (.pipe (.dest gulp "build/markdown-explained"))))

这是我用来编译的命令

lein cljsbuild once gulpjs

Compiling ClojureScript.
Compiling "gulpfile.js" from ["src/gulpjs"]...
Successfully compiled "gulpfile.js" in 3.316 seconds.

但是我有一个奇怪的输出 gulpfile.js,它看起来根本不像 Node 代码,为什么会这样错呢???

goog.addDependency("base.js", ['goog'], []);
goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.object', 'goog.string.StringBuffer', 'goog.array']);
goog.addDependency("../cljs/nodejs.js", ['cljs.nodejs'], ['cljs.core']);
goog.addDependency("../gulpjs/core.js", ['gulpjs.core'], ['cljs.core', 'cljs.nodejs']);
3个回答

12

因为你的目标是nodejs,编译器选项中第一件你缺少的是

:target :nodejs

其次,如果您使用:optimizations :none,则也会错过选项output-dir

:output-dir "out"
这是关于编译器选项和特性的简洁介绍:http://slides.com/joakino/diving-into-clojurescript/#/5(在幻灯片中往下滑)
然后在您的主文件中,您需要设置一个主函数,并且最好启用控制台打印:
(ns cljs-gulp.core
  (:require [cljs.nodejs :as nodejs]))

(nodejs/enable-util-print!)

(defn -main [& args] ... )

(set! *main-cli-fn* -main)

然后,实际上您可以在Node.js中使用任何模式,但默认情况下可用的模式是simpleadvanced。对于none,您需要一个包装器文件来使节点能够加载闭包依赖项,因此例如创建一个名为index.js的文件并将以下内容放入其中:

require('./out/goog/bootstrap/nodejs')
require('./cljs_gulp') // Name of the js ouput file
require('./out/cljs_gulp/core') // Path to compiled core file
cljs_gulp.core._main() // appname.namespace._mainfunction

编译后,您应该使用node index.js而不是node cljs_gulp.js。这非常好用,并且您可以利用超快的重新编译时间。

这篇文章解释得非常清楚,而且很新:http://blog.lauripesonen.com/clojurescript-optimizations-on-node-huh/

以下是代码:(我的项目名称是cljs_gulp生成的,因此请更改以适应您的项目)

project.clj

(defproject cljs_gulp "0.1.0-SNAPSHOT"
  :description "Where I want to learn about clojurescript"
  :url "http://example.com"

  :dependencies [[org.clojure/clojure "1.7.0-alpha2"]
                 [org.clojure/clojurescript "0.0-2322"]]

  :plugins [[lein-cljsbuild "1.0.4-SNAPSHOT"]]

  :source-paths ["src"]

  :cljsbuild {
              :builds [{:id "gulpjs"
                        :source-paths ["src/cljs_gulp/"]
                        :compiler {
                                   :target :nodejs
                                   :output-to "cljs_gulp.js"
                                   :output-dir "out"
                                   :optimizations :none
                                   :pretty-print true}}]})

src/cljs_gulp/core.cljs

(ns cljs-gulp.core
  (:require [cljs.nodejs :as nodejs]))

(nodejs/enable-util-print!)

(def gulp (nodejs/require "gulp"))

(def gulp-livereload (nodejs/require "gulp-livereload"))

(def gulp-markdown (nodejs/require "gulp-markdown"))

(def gulp-watch (nodejs/require "gulp-watch"))

(defn -main [& args]
  (.task gulp "markdown"
         #(-> (.source gulp "../markdown-explained")
              (.pipe (gulp-markdown))
              (.pipe (.dest gulp "build/markdown-explained")))))

(set! *main-cli-fn* -main)

有几个cljs的node模板非常有帮助,可以帮助您开始使用cljs和node,而不是浏览器:


3

这是因为你正在使用:optimization :none模式。

此模式旨在进行快速的重新编译,适用于积极开发。这样cljsbuild就可以重新编译仅更改的文件而不影响其他内容。

如果您想获得单个js文件,可以使用以下任一方法:

:optimizations :simple
:optimizations :advanced

这将需要更多时间,但会创建一个包含所有依赖项的单个文件。 :advanced 模式也会为您清除死代码,从而使目标文件更小。 但是,由于闭包编译器的性质,在使用它时应该小心,这在这篇文章中有很好地描述。

谢谢兄弟,你的答案是正确的,但@Joaquin的答案更加周到和出色 :) - babygau

0

如之前的答案所述,ClojureScript 默认情况下会被编译为浏览器使用。如果要确保其被编译为 Node.js 环境下可用,则需要在配置中某处指定 :target :nodejs

另外,值得一提的是 lein-cljs 并不是 ClojureScript 的唯一编译工具。如果您想尝试其他解决方案,可以考虑使用 shadow-cljs(https://github.com/minimal-xyz/minimal-shadow-cljs-nodejs)。

此外,ClojureScript 编译出来的代码使用 Closure JS 编写,使用 goog.x.y.z 创建模块系统。因此,您需要接受其代码看起来与 CommonJS 相比差异较大的现实。然而,如果您坚持要使用 CommonJS,可以使用 shadow-cljs 并指定 :target :commonjs


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接