4

Consider the following trivial clojurescript program:

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

(defn -main [& args]
  (println "args: " args)
  (let [one (first args) two (second args)]
    (println "one: " one)
    (println "two: " two)))

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

Problem: If I compile this with no optimizations, this program works as expected. Example:

$ node program.js 1 2
=> args: (1, 2)
   one: 1
   two: 2

If I compile the program with advanced optimizations, then my program doesn't recognize arguments:

$ node program.js 1 2
=> args: nil
   one: nil
   two: nil

What could be causing this?

EDIT: Adding the following externs seems to fix the issue:

var node = {};
node.process = {};
node.process.argv = {};

In addition, taking out the node parent object and just using process also fixes it:

var process = {};
process.argv = {};

I'm not really sure I even understand my own solution though. I guess behind the scenes clojurescript is passing node.process.argv to -main?

6
  • 1
    Usually you don't minify code for node.js. That's a good question anyway. Commented Jan 6, 2016 at 20:11
  • Wait -- you shouldn't be using the advanced compilation option when targetting nodejs? Why would that be? Commented Jan 6, 2016 at 20:19
  • 1
    advanced compilation is to reduce the size of the generated .js, which is very important in browsers as it will be downloaded on page load, but almost useless in the server side Commented Jan 6, 2016 at 20:26
  • I thought, in addition to reducing the size of the .js, it non-trivially improved performance? Commented Jan 6, 2016 at 20:30
  • @user1770201 the usual reason to do that for node is to obfuscate the code, not to gain performance. Commented Jan 6, 2016 at 20:42

1 Answer 1

3

As I said in the comments, minimizing Node.JS code it not exactly the usual path, and will likely not result in significant performance improvements. The only valid reason that I can think of is to obfuscate the code.

Anyway, you could use an extern file (as you found out), or you can use *main-cli-fn*

As described here : http://www.matthewstump.com/misc/2012/06/04/writing-nodejs-modules-in-clojurescript/

(ns sample.core
  (:require [cljs.nodejs :as node]))

(defn blargl
  []
  (println "blargl!"))

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

And compile it with the following options :

cljsc src '{:optimizations :simple :pretty-print true :target :nodejs}' > lib/sample.js

The default extern file is there. You can also see an example of this variable being used there.

Also, the ClojureScript Wiki for Node.js has just been edited to reflect that :

Note: Under Node.js there is little reason to use advanced optimizations. While advanced optimizations does apply performance related optimizations, these are now largely obviated by optimizations present in modern JavaScript virtual machines like V8, SpiderMonkey, and JavaScriptCore. For Node.js, :simple or :none optimizations suffice and using them removes the need for extra steps like supplying an externs file.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. I don't have a stake in this fight (lust learning/tinkering), but I just ran a compilation comparison between :advanced and :simple and saw a gain of ~200ms using the :advanced option when targetting nodejs. Since the program I ran the test on is a CLI utility, that seems non-trivial to me. On the other hand, constantly updating an externs file makes writing ClojureScript feel like writing C++ (slowly declaring everything, etc). Not sure what to think here. :(
@user1770201 Don't have a stake either :) Out of curiosity, from how much time to how much time (and roughly how big is your CLI app) ?
~1,000ms -> 800ms was the differential. About 100 lines of clojurescript code + 100 or so lines of pure JavaScript interop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.