【问题标题】:How to compile clojurescript to nodejs?如何将clojurescript编译为nodejs?
【发布时间】:2014-09-12 07:55:18
【问题描述】:

为什么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,它看起来根本不像节点代码,为什么会这么错误???

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']);

【问题讨论】:

    标签: clojure clojurescript


    【解决方案1】:

    由于您以 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)
    

    然后,你实际上可以在 nodejs 中使用任何模式,但默认工作的模式是 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,因此请更改以适合您的名称)

    项目.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 节点模板非常有助于开始使用 cljs 和 node,而不是浏览器:

    【讨论】:

      【解决方案2】:

      发生这种情况是因为您使用的是:optimization :none

      此模式旨在通过快速重新编译进行主动开发。这样cljsbuild 可以只重新编译您更改的文件,而无需触及其他内容。

      如果你想获取单个 js 文件,你应该使用以下任一:

      :optimizations :simple
      :optimizations :advanced
      

      这将花费更多时间,但会创建一个包含所有依赖项的单个文件。

      :advanced 模式还会为您清理死代码,从而使目标文件更小。 但是你应该小心使用它,因为它有一些陷阱,因为闭包编译器的性质很好地描述了in this article

      【讨论】:

      • tks 兄弟,你的回答是正确的,但@Joaquin 的回答更周到也更棒:)
      【解决方案3】:

      如前面的回答中提到的,ClojureScript 默认编译到浏览器并处于开发模式。为了确保它被编译为 Node.js ,您需要在配置中的某处指定 :target :nodejs

      我想补充一点,lein-cljs 不是 ClojureScript 的唯一编译器工具。如果您尝试https://github.com/minimal-xyz/minimal-shadow-cljs-nodejs,shadow-cljs 可能是一个更好的解决方案。

      此外,从 ClojureScript 编译的代码是用 Closure JS 编写的,它使用 goog.x.y.z 来创建其模块系统。所以你必须承认代码看起来不像 CommonJS 的事实。但是,如果您坚持,您可以使用 shadow-cljs 并指定 :target :commonjs

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        相关资源
        最近更新 更多