How to compile clojurescript to nodejs?


How to compile clojurescript to nodejs?



Why cljsbuild does not compile gulpfile.js file properly?


cljsbuild


gulpfile.js



Here is my project.clj config:


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}}]})



Here is my core.cljs


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"))))



Here is command I used to compile


lein cljsbuild once gulpjs

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



But I have this strange output gulpfile.js, it doesn't look like node codes at all, why it is so wrong???


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




3 Answers
3



Since you are targeting nodejs, first thing that you are missing in the compiler options is


:target :nodejs



Second, if you use :optimizations :none you are missing too the option output-dir:


:optimizations :none


output-dir


:output-dir "out"



Here is a nice briefing on the compiler options and characteristics: http://slides.com/joakino/diving-into-clojurescript/#/5 (Go down in the slides)



Then in your main file, you need to set a main function and it is nice to enable console prints:


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

(nodejs/enable-util-print!)

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

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



Then, you can actually use any mode in nodejs, but the ones that work by default are simple and advanced. For none you need a wrapper file to make node be able to load closure dependencies, so create a file named index.js for example and put this in:


simple


advanced


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



And after compiling you would node index.js instead of node cljs_gulp.js. And that works awesome, and you take advantage of the super fast recompilation times.


node index.js


node cljs_gulp.js



This article explains it all pretty well, and it's recent: http://blog.lauripesonen.com/clojurescript-optimizations-on-node-huh/



Here is the code: (my project name was generated as cljs_gulp, so change that to fit yours)



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)



There are a couple of cljs node templates that are very helpful for getting started on cljs and node, instead of the browser:



This happens because you're using :optimization :none.


:optimization :none



This mode is aimed for active development with a rapid recompilation. That way cljsbuild could recompile only the file you've changed without touching other stuff.


cljsbuild



If you want to get a single js file, you should use either of following:


:optimizations :simple
:optimizations :advanced



This will take much more time but creates a single file with all dependencies included.



:advanced mode will also clean dead code for you, thus making the target file even smaller.
But you should be careful using it, due to it have some pitfalls by the nature of closure compiler nicely described in this article.


:advanced





tks bro, your answer is correct but @Joaquin answer is more thoughtful and great either :)
– babygau
Sep 12 '14 at 9:46



As mentioned in previous answers, ClojureScript is compiled to browser and in development mode by default. To make sure it's compiled to Node.js , you need to specify :target :nodejs somewhere in the configurations.


:target :nodejs



I want to added that lein-cljs is not the only compiler tool for ClojureScript. shadow-cljs can be a better solution if you try https://github.com/minimal-xyz/minimal-shadow-cljs-nodejs .


lein-cljs



Besides, the code compiled from ClojureScript is written in Closure JS, which is using goog.x.y.z for creating its module system. So you have to bare the fact that the code looks far less like CommonJS. However you can use shadow-cljs and specify :target :commonjs if you insist.


goog.x.y.z


:target :commonjs






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

C++ thread error: no type named ‘type’ MINGW

Decreasing a static image progress bar horizontally in SDL

How to input without newline? (Python)