Macchiato – A way to build Node web applications using ClojureScript
macchiato-framework.github.io
macchiato-framework.github.io
I just can't imagine many situations where you have cl/cljs capable devs yet want to reject all the benefits of the jvm and use node
The jvm is still a really good runtime. Java is a way more consistent language than javascript. Other languages running on top of the jvm are way more beautiful and sensible than javascript. The jvm can be leveraged many ways when it comes to performance and use cases, and I consider it way more stable than different javascript runtime implementations running in different browsers coded by different organizations.
Out of curiosity, why do you think the JVM is such a thing of the past and so bloated and clunky? I'm curious about what reasons people have. From my own experience, I get that javascript is easy to start things in, but damn, it can get sucky once you have to maintain and refactor a bigger codebase. It just feels like javascript and node gets a lot of mindshare since it is what the web industry pushes down everyones throat sometimes :/
But if you're interested in one way Node is nice: single-threaded + unified way to write async code.
I just took some example languages, maybe I shouldn't have as it polluted my point with my own biases. It also felt relevant to bring them up, since it is what people mostly end up writing in, on those respective platforms. But I'm mostly interested in the JVM vs. node discussion though and opinions.
Yeah, the single threaded model + async can be nice and resolve problems with race conditions etc. making one headache go away. But it can also be a limiting factor that you cannot change if you need to, but then you maybe choose the wrong tech to begin with if your use case can include high cpu usage etc.
What often astounds me in these kinds of discussion: People just seem to assume that's not possible with the JVM.
So, just for the record (not neccesarily directed to you :) ): You can totally do node.js style (event-driven, async, nonblocking, no-shared-state - "single-threaded", if you will) with the jvm, and it works great (e.g. vertx, netty, play and many others).
And as you said: Contrary to node, with the JVM there's no danger of it being a limiting factor you're stuck with.
It's totally different. There is no unified solution. Just about every library is blocking the thread and you have to code around that. And the solutions don't interop. And they can be atrocious abstractions: https://docs.oracle.com/javase/8/docs/api/java/util/concurre...
I work with Netty professionally and I would not call that a pleasant experience.
Async programming in Node has really good ergonomics that are hard to find elsewhere. For example, compare Promise.map(..., { concurrency: N }) to the Go solution.
And yeah, of course there's no single unified solution - the JVM landscape isn't restricted to a single programming model. That's actually its strength. Just because not every solution, every model works well together, doesn't mean that "the solutions don't interop" in general. (what are "the solutions"?)
And your general statement about "ergonomics that are hard to find elsewhere", yeah, that would really need a bit more than a small promise example to back it up...
One reason I might be interested in running clojurescript on node.js is because most web technologies nowadays are written for node.js/javascript first and ported as an afterthought. GraphQL servers on Clojure/Java, for example, are like 3rd class citizens compared to node.js. Google provides nice wrappers to their APIs as long as you're not using clojure. I end up writing things in-house a lot more often than I would with node where I just npm install the package I want and I get something that is maintained by the official author.
~ time java test
Hello world
java test 0.11s user 0.03s system 88% cpu 0.161 totalMacBook Pro (Retina, 15-inch, Late 2013)
Wrong. JVM is fast to start. Clojure is slow to start.
The (Clojure) "JVM Slow Startup Time" Myth
Like cljs ontop of node?
I think a lot of people are wrongly under the impression that the JVM is complicated, and annoying to use. It is not, Java is. Java is not the JVM, and in the context of Clojure and ClojureScript, the JVM is amazing.
The only reason not to use the JVM I'd say would be cases where you need sub-second start times, or you have memory and space constraints, or need full real time. Though for the latter two, there exist paid JVMs that can work for those use cases. In fact, that's another amazing thing about the JVM, its a standard, and there exist multiple fully functional implementations.
Some benefits of the JVM are its very complete standard library, as well as its gigantic set of third party libs. It runs on almost any imaginable hardware. It is extremely fast. All other VMs or even VMless GC runtimes benchmark themselves against it because its the known performance champion. It has amazing GCs, it even has more then one type of GC. It supports multiple programming languages, such as Clojure. It comes with top notch tooling support for debugging, profiling and monitoring. Finally, its backed by a lot of money, which means it keeps improving quickly. Some of its soon to be improvements are complete modularity, AOT compilation, faster startup time, smaller memory footprint, ability to call native code and use native data and finally support for first class fibers (like erlang and go threads).
But seriously completely agree with you about the jvm being awesome. However clojure var load times on top of the base jvm and memory use makes it dog slow to start a development repl(30+ seconds is normal.. queue comment about how someone only restarts their repl every couple of days LOL) and unsuitable or unusable for situations where you care about app start times of less than 10 seconds and memory constrained environments such as cli, iot, serverless, android.
The (Clojure) "JVM Slow Startup Time" Myth
$ time clj -e '(System/exit 0)'
clj -e '(System/exit 0)' 1.60s user 0.07s system 198% cpu 0.839 total
It takes about 2 seconds to start for me.In this case I suspect cursive is fast because:
* You have a JVM loaded in the form of IntelliJ * You only need to start Clojure inside that JVM (which is reduced from the time clj takes!)
So 1 second is a reasonable time from IntelliJ=>Clojure. 2 seconds is reasonable for Nothing=>Clojure.
So the actual time was 0.839s.
Which means Clojure 1.9 on your computer boots and shutdowns its repl in under a second.
badum tsss
But jokes aside - the whole node environment doesn't strike me as particularly un-bloated or un-clunky, especially compared to modern JVM solutions like e.g. vertx, netty or even wildfly/undertow. Same goes for the pure runtime itself (i.e. v8 vs jvm), where v8 may be competitive at best, but hopelessly outclassed in other cases.
Perfect for "Serverless"
I want off this ride!
Serverless means you don't manage any servers, directly or indirectly. It's a step further towards where you don't own any servers.
It's part of an evolution that has gone from being more aware of servers to being less aware: on-site servers -> colocated physical servers -> dedicated servers -> virtual private servers -> cloud virtual private servers -> autoscaled cloud VPS -> cloud functions where you you aren't billed by, or even aware, of the number of servers running
I don't think "serverless" is a terrible term.
With Clojure(Script) whole categories of complexities tend to disappear, so I'd expect that to be the case in this scenario too.
The other reason is that there are lots of people who work with JavaScript and are not interested in the JVM ecosystem. I think it's good to have an option that targets this demographic.
One of the goals for Macchiato is to provide a Ring compatible API. This allows you to start projects on Node and move them to the JVM as they grow.
Slow startup of Clojure's code, it's Clojure own doing.
The (Clojure) "JVM Slow Startup Time" Myth - http://blog.ndk.io/jvm-slow-startup.html
I guess the less than inspiring names "short black" and "long black" are available? :)
But Macchiato seems to imply that something was previously stopping us, which it solves, so I'm curious to know what that is, since I was under the impression it was already possible.
-he goal for Macchiato is...
should be:
The goal for Macchiato is...
https://clojurescript.org/guides/self-hosting
[Edit to correct: the following is no longer entirely valid: see downthread.]
That said, if you want to benefit from the Google Closure optimizations, you currently do need to use the JVM toolchain. IIRC, there's been work on the Google Closure side to run without a JVM, and if that's the case, there may be opportunities in the future to take advantage of this in the ClojureScript toolchain.
Its a ClojureScript compiler built in ClojureScript, which creates NodeJS targets.
Self-Hosted ClojureScript's current downside is that it does not support as many of the ClojureScript libs.
That said, the use of the JVM by ClojureScript is just as a build tool. Don't you already have Java installed on your computer anyways?