How to compile clojurescript to nodejs?
Asked Answered
B

3

9

Why cljsbuild does not compile gulpfile.js file properly?

Here is my project.clj config:

(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

(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???

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']);
Biddle answered 12/9, 2014 at 7:55 Comment(0)
A
12

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:

: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:

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.

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:

Amortizement answered 12/9, 2014 at 9:39 Comment(0)
F
3

This happens because you're using :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.

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.

Ferriferous answered 12/9, 2014 at 8:56 Comment(1)
tks bro, your answer is correct but @Amortizement answer is more thoughtful and great either :)Biddle
A
0

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.

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 .

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.

Andyane answered 30/6, 2018 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.