You can find the project in Github.
I tried to replicate the Clojure namespace structure to the equivalent Node structures so that it is easy to compare various parts of the application in these two implementations (e.g. server.js — server.clj)
Visual Studio Code
I googled which frameworks are the most popular unit testing frameworks to be used with Node — Mocha seemed to be the one. You can see the unit tests that I implemented as an exercise in the test directory.
Testing is the area where Node really shines. I have never seen a web server starting so blazingly fast in API testing, and also shutting down after tests. Just look at the server.js — before and after functions and try to run ‘npm test’ — damn, it’s fast.
2018-10-01 20:06:36.555 DEBUG Before tests start the webserver...
2018-10-01 20:06:36.569 DEBUG ENTER server.getInfo
2018-10-01 20:06:36.571 DEBUG EXIT server.getInfo
✓ respond with json
2018-10-01 20:06:36.576 DEBUG After tests shutdown the webserver...
There were three libraries that were helpful when implementing the unit tests: The assert library which provided the overall unit testing framework, the underscore library for checking object equality, and the supertest library which provided tools for checking http return values, returned response body etc.
The testing framework output is also pretty clear to read, e.g.:
SS_LOG_LEVEL=error npm test
Should be two product groups in domain db
✓ getProductGroups returns object with 2 items
✓ getProductGroups second time (from cache), returns object with 2 items
Should be 35 products in product group 1 / domain db
✓ getProducts for pg 1 returns list with 35 items
✓ getProducts for pg 2 returns list with 400 items
Should find product for pgId=2 and pId=49 in domain db
✓ getProduct for pgId 2 and pId 49 returns list with 8 items
Node is fast, that was my first observation. A short comparison running unit tests in Node vs. Clojure/Lein/JVM in command line:
- Node npm/Mocha (time npm test): 0m0.634s
- Clojure Leiningen (time lein test): 0m2.605s
I.e. Node starts immediately and runs the tests. JVM boots very, very slowly, then loads Clojure jar, then loads project class files, then runs tests, and some 2,5 seconds of my precious time has been consumed that I will never get back in my life.
Well, this comparison doesn’t tell the whole truth. With Clojure REPL you don’t actually run the whole project unit tests at once but you work on a namespace and load it onto REPL and experiment with it — which happens immediately since JVM and Clojure jar have already been loaded into the IDE.
Node REPL is pretty good, a bit like Python REPL, but not anything like a real Lisp REPL, of course. The following code snippet is copy-pasted from the Node REPL when experimenting if there are no nulls or empty strings in a list:
!['a', '', 'c'].some(item => ((item == null) || (item == undefined) || (item == '')) )
Other Development Experiences
Hot code reloading. You can use nodemon to watch any changes in your code base and automatically restart your node server — excellent during development.
Cross-origin resource sharing (CORS). I was a bit puzzled that there were no CORS issues. You just had to import the cors module and tell Express server to use it and that’s it (compared to rather lengthy debugging session I had to spend in the Clojure side to get all CORS issues fixed).
Asynchronous Programming Model
The asynchronous programming model makes Node super fast in non-cpu-intensive tasks, so there are benefits to balance the more complex programming model. See more here.
Backend. Definitely yes. If I can freely choose the backend stack I would probably go for Java/Spring in enterprise type of heavy stuff with a lot of developers, Clojure in a bit more relaxed data oriented backend system, probably Python when implementing short serverless functions in AWS/Azure. But there are a lot of Node implementations out there and if some team is already using Node — no problem, let’s use Node.