Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Macchiato – A way to build Node web applications using ClojureScript (macchiato-framework.github.io)
132 points by tosh on Dec 21, 2017 | hide | past | favorite | 66 comments


I have to admit I thought it was some kind of meta joke about the state of development right now.

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


There are situations where you might want something lighter than the JVM. If startup time matters or you want a low memory footprint then JVM is not ideal.

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.


The JVM startup is quite fast, and it can be made even faster when using a JVM that supports AOT compilation to native code.

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


Sure, Clojure adds a lot of overhead on top of the JVM. However, even large Java apps can take seconds to startup. If you're targeting something like AWS Lambda, that's a no go.


I'd use cljs for Serverless architectures. There's JVM support in e.g. AWS Lambda, but JS is a more popular and lightweight target.


That seems strange. Having used clojurescript and clojure in production for years, it’s a very niche language that only makes sense for a small subset of use cases, similar to elm’s story. And all of those use cases benefit from the JVM specifically. The slimmer node environment is not a plus in situations when clojure or clojurescript would make sense.


As someone learning Clojure, I'm curious why you feel Clojure is not applicable to most use cases. From an outsider's perspective, it seems like a great fit for most enterprisey type applications which seem to make up the majority of apps. Would love to hear more about your experience with Clojure.


Clojure(Script) is a general-purpose language.


How's that working for you compared to vanilla node on serverless? And are you using it for an API or just minor services?


Thanks for the question but I haven't tried it myself (yet).

With Clojure(Script) whole categories of complexities tend to disappear, so I'd expect that to be the case in this scenario too.


I’d be curious which whole categories just disappear in Clojure/Script that JS has, in real world practical situations.


Mutability, boilerplate, no built-in mechanisms/conventions for saner programming, tooling/trend hell


"MACCHIATO: ClojureScript arrives on the server"

Perfect for "Serverless"

I want off this ride!


Serverless stacks do run on servers, and on node.js in this case.


We're drowning in obfuscation.


It's on the server side, but you don't manage any servers.

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.


The JVM, for all it's benefits, comes with a significant number of downsides. Many folks no longer wish to operate a JVM when less bloated and clunky runtimes exist.


You'll have to specify what you mean by the JVM being bloated and clunky.

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


I think you meant to say sub 20 second start times for clojure apps :)

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.


My repl starts in about a second... maybe it’s because I’m using cursive


Whatever your setup, there is no way you are starting a JVM from scratch and then loading a Clojure REPL in one second. I promise you that is not happening.


Have you tried the new clj command line tool from Clojure themselves?

  $ 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.


Its not 2 seconds. With the time command, you have to look at the elapsed time. Clojure does parallel execution, that's why you see CPU at 198%. So the user and sys time are the sum of the time on each cores.

So the actual time was 0.839s.

Which means Clojure 1.9 on your computer boots and shutdowns its repl in under a second.


I'm lost. I have Java 9 and the latest Clojure 1.9 plus Leiningen. No 'clj' in my PATH. Where does this new command live?


See the getting started guide on how to install the CLI. https://clojure.org/guides/getting_started


Blame Clojure's implementation.

The (Clojure) "JVM Slow Startup Time" Myth

http://blog.ndk.io/jvm-slow-startup.html


Well, there is an OpenJDK version that azul systems make called zulu, which is open source and free from oracle.

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


JVM is slow as heck to start, but an awesome runtim. In an ideal world I'll never have to restart my application or my repl, but in the real world I do it all the time. It's much faster than node.js/V8 when executing heavy tasks.

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.


Not it is not, blame Clojure implementation.

The (Clojure) "JVM Slow Startup Time" Myth

http://blog.ndk.io/jvm-slow-startup.html


  ~ time java test
Hello world java test 0.11s user 0.03s system 88% cpu 0.161 total

MacBook Pro (Retina, 15-inch, Late 2013)


I think what's missing in your parent but assumed is, within the context of Clojure, startup is slower than ClojureScript. The Clojure runtime is relatively slow on startup.


Unless you restart your server 400 times a day, how does startup times matter, even remotely?


I think your question is better directed upthread: I'm attempting to clarify possible misunderstandings, not arguing for any particular position. But it's important to keep in mind that people have different needs and desires in different contexts. One off the top of my head is something like AWS Lambda. It's not necessarily the context where Macchiato would play a role, but a server context where one might indeed be starting up processes thousands of times a day.


> JVM is slow as heck to star

Wrong. JVM is fast to start. Clojure is slow to start.


The parent may be assuming "Clojure on the JVM" as opposed to the JVM alone. Loading the Clojure runtime on the JVM can be slow.


Well, you're writing ClojureScript in TFA so I'm not sure what Java vs Javascript has to do with it.

But if you're interested in one way Node is nice: single-threaded + unified way to write async code.


From my understanding, the article is about leveraging clojurescript serverside on nodejs. Then someone asks why just not write in clojure serverside on the jvm.

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.


>Yeah, the single threaded model + async can be nice and resolve problems with race conditions etc. making one headache go away.

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.


Nobody said it's not possible to do it on the JVM. It's also possible to do it in C.

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.


Huh? Just about every library is blocking? Maybe x years ago. Get with the times.

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


Yes, you can often find async Java libraries to fit your architecture, but those are usually less mature than the thread-based ones. With Node libraries, your architecture is set, so you are free to pick the library that best meets your needs. This is a substantial benefit, which I say as someone who loves and regularly uses the ClojureScript on Node model and selected it only after running into this exact problem with Clojure on the JVM.


Maybe, but what has that to do with node.js?

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.


>less bloated and clunky runtimes exist.

Like cljs ontop of node?


This isn't particularly helpful. Do you have something to add besides answering a question with another one? People have different use cases and different needs, and in general is a good think to have options with Clojure/Script. If you think ClojureScript on node is misguided, please provide more argument as to why and help move the discussion forward, regardless of how wrong you might feel the comment you're responding to is.


Like what? :-)


In this particular case, it looks like the author is preferring to target the Node runtime.


Server-side rendering of React applications is a pretty good reason to use Clojure on node as your server. Definitely not my preference of runtime but it does make this (quite common) use case substantially simpler for at least small- to medium-sized apps.


How about the huge number of companies that already use nodejs with great success, and don't want their developers to have to learn yet another platform(jvm), and be able to use a single platform for both server and client?


How many more coffee drink names are available for the taking? Do we reach peak javascript when that list is exhausted?


There's two JS libraries using the term "ristretto", we've all heard of mocha. "espresso" seems to be a disused node.js tooling library, similarly, "flat white" is a disused CMS, "latte" is a failed CoffeeScript competitor. "Americano" seems to be a slightly more used tooling repository.

I guess the less than inspiring names "short black" and "long black" are available? :)


Then you'd love LuneOS. Every release name is a coffee drink.


How about "shot in the dark"?


I've been loosely following the development for a while. Glad that it's not dying and seems to be going somewhere, but not quite ready to build anything big on it yet (which I guess can be self fulfilling... someone has to build something big on it sometime to increase visibility)


What stops you from using ClojureScript on the server today?


What stops you from using clojure on the server today?


Nothing, and I believe there's also nothing stopping you from using ClojureScript on the server today either with Nashorn or Nodejs.

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.


The goal of Macchiato is to provide an idiomatic way to write Clojure apps on top of Node that mimics the way Clojure web stack works on the JVM.


You have a typing error under from closure:

-he goal for Macchiato is...

should be:

The goal for Macchiato is...


I think it should say "ClojureScript arrives on THE server", with the article.


I keep looking at ClojureScript, and decide to try it. And then I get to the "requires JDK" and just turn around and walk out the door. It seems like an interesting language, but it would be nice to have it run without that requirement.


That's no longer true. ClojureScript can now be self-hosted.

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.


Lumo took advantage of that already according to https://anmonteiro.com/2017/02/compiling-clojurescript-proje...


Thanks for the link. I expected it was just a matter of time!


It can, look at lumo: https://github.com/anmonteiro/lumo

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?


The fact that you "just walk out of the door" says more about you than about clojurescript or the jvm.


Why? (Honest question)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: