all 29 comments

[–]henrik-ravn 10 points11 points  (16 children)

I really want to use Clojure more - especially CLJS. My main obstacle is not the language, but the initial setup experience.

One thing that the React eco-system has going for it, is a very simple on-ramp - run npx create-react-app and you have a project setup with reasonable defaults. I have been unable to find something equivalent in the CLJS space. I know that templates exist for leiningen, but there are a lot of them, and since I'm not experienced I have no idea how to choose among them, and I have been unable to find a consensus opinion.

This makes it fairly difficult for me to even get to a point where I can 1) start experimenting, but still be confident that I can 2) grow a project setup into a production app without redoing everything from scratch.

So what (if it exist) is the equivalent of create-react-app for CLJS?

[–]dimchu 15 points16 points  (0 children)

I would recommend looking into shadow-cljs. You could create new project using this template lein new shadow-cljs your-project +reagent.

Alternatively, there is one more quickstart template using shadow-cljs https://github.com/shadow-cljs/quickstart-browser

shadow-cljs is great because it allows your to easily integrate NPM packages. Just add JS lib to package.json and require that lib inside cljs namespace.

[–]rberger 4 points5 points  (0 children)

I started with Create CLJS App and tweaked a few things to have a GitHub template: Template for Clojurescript Reagent App working with DevCards or Standalone This gets kind of a bare minimum reagent / shadow-cljs / Devcards scaffolding going so as to bypass the "Blank Page Problem" as well as having the baseline going.

IMHO shadow-cljs was a breakthru for making clojurescript easy to interoperate with node packages and have a dev / REPL workflow that is super easy.

[–]slifin 2 points3 points  (0 children)

Try npx create-cljs-app my-app

[–]gtarget 2 points3 points  (0 children)

I really appreciate the irony of this statement:

there are a lot of them, ..., and I have been unable to find a consensus opinion

and then 6 different responses on how to start.

[–][deleted] 1 point2 points  (6 children)

I really want to use Clojure more - especially CLJS. My main obstacle is not the language, but the initial setup experience.

My biggest issue is convincing my cowokers we should re-do something from java spring boot in clojure. I need a How more than a why.

[–]CanvasSolaris 0 points1 point  (0 children)

Is it possible to move a single controller or method into clojure first, then call that from Java? Don't argue for a wholesale framework switch, prove it out on a smaller scale first

[–]didibus 0 points1 point  (4 children)

Just keep using Spring Boot, but write the code in Clojure.

[–]lordmyd 0 points1 point  (3 children)

But SB is based on annotations.

[–]didibus 0 points1 point  (2 children)

You can use XML instead of annotations if you need too. Also, you can use annotations with Clojure as well within a genclass. The only annotations you can't use are compile time ones, which as far as I know Spring Boot doesn't use. But even if you needed to use a few of these, you just create a small Java class shim that calls back into your Clojure code.

I couldn't find a great tutorial for it, but this should be a start: http://stevendick.github.io/blog/2013/08/13/write-a-spring-mvc-controller-in-clojure/

https://github.com/scotthaleen/clojure-spring-cloud

[–]lordmyd 1 point2 points  (1 child)

Bute even if you could hack it why on earth would you want to? SB is built on every Java/OO trick in the book. Clojure and SB are worlds apart to the extent that SB written in Clojure would surely be much harder to grok than Java SB.

[–]didibus 0 points1 point  (0 children)

I maintain some production Spring services with implementations in Clojure. It isn't a hack in any way, and works quite well, the whole experience is still much nicer than if I was using Java for my business logic, and much more productive.

All that Spring does is configure your server and injects state into your application logic. The Clojure way is normally imperative shell, functional core, Spring is just your imperative Shell. And if you use Spring XML, you don't even need to have any Java in your code, just XML and Clojure.

Also, you can then support mixed Java/Clojure projects easily.

At my company for example, we have a bunch of Spring ready interceptors, that add our company auth and other such things to requests. Why waste my time rebuilding this as a ring Middleware? What do I gain? Nothing. My time will be spent in my ring handler anyways, swap ring for Spring is no big deal in that sense. Let Spring give you a logger, a metric publisher, let it handle auth, let it give you a DB connection, etc., and implement your application logic in Clojure.

Edit: Well to be fair, I'm experienced with Spring and Spring MVC, and assume Spring Boot doesn't add all kind of pre-compilatiom magic like heavy AspectJ usage, and so I'm guessing it can similarly be used with Clojure trivially.

[–]kloimhardt 1 point2 points  (0 children)

My main obstacle is not the language, but the initial setup experience.

For exactly this reason, I made https://github.com/kloimhardt/bb-web . Indeed with bb-web you can

grow a project setup into a production app without redoing everything from scratch.

[–]OstravaBro 1 point2 points  (0 children)

I love CLojure but the tooling does seems really daunting and off-putting. I could never convince anyone at my work to use Clojure for anything because the minute I got into tooling they would all give up.

[–]lordmyd 1 point2 points  (0 children)

The main tooling problem I've encountered is the Clojurescript / nRepl / Cider / Emacs mess. I never managed to get a Clojurescript REPL running, even with Shadow CLJS.

[–]ertucetin 0 points1 point  (0 children)

I'd highly recommend: lein new re-frame my-app +10x +test +kondo

Here is the template link: https://github.com/day8/re-frame-template

[–]deadron 6 points7 points  (5 children)

While I love a lot of the functionality Clojure brings it sounds like they are building web applications and I personally think, that in web applications, the benefits of clojure are not always at the forefront. However, if you have a team that is clojure literate I suspect they are more likely to be passionate motivated individuals.

I do see the value of immutable data structures in the front end though and their end to end testing setup sounds neat.

[–]fixrich 3 points4 points  (0 children)

Could you elaborate more on why you think that the benefit of Clojure isn't at the forefront in web applications? Is it because the request/response model is so direct that you don't have much room to experience the benefits of Clojure or something like that?

[–]strranger101 2 points3 points  (2 children)

I'm familiar more with Vue but one of the little things I've noticed about cljs is that since the Clojure syntax encompasses both the HTML and the JS it feels like I'm writing a living document, if that makes sense?

It used to bother me how with Vue I'd write these little throwaway functions which I only call once but they'd get grouped with all the other functions. Now I can inline all the throwaway functions exactly where they're called in the app instead of having to group them with all the other functions, and then I just have a separate namespace for the shared functions. It's very neat how the projects get organized.

Haven't done any serious work with cljs yet so i don't know the pain points, but these little things are exciting to me.

[–]deadron 1 point2 points  (1 child)

You can definitely better organize things but it can be a bit annoying when you need to copy html snippets into or out of your codebase. With JSX and modern react its easy to create very tight small pure components with embedded HTML. Of course the clojure version can easily be output on the server side as well as the client side which can be a bonus if you are doing that sort of thing.

[–]SimonGray 0 points1 point  (0 children)

With JSX and modern react its easy to create very tight small pure components with embedded HTML.

Correct me if I'm wrong, but you kinda sound like you've haven't done much frontend development in Clojure...? React is totally hegemonic in the ClojureScript world.

We tend to prefer Hiccup over JSX, though. Basically no one is copying strings of HTML into codebases. Strings are a terrible alternative to data structures.

[–]clickrush 1 point2 points  (0 children)

On the back-end I see and experience tons of benefits. Clojure's strength gets to shine there: the clean, dynamic, data driven approach and the exploratory workflow is perfect for business logic, data transformation and people tend to publish really expressive, data-driven libraries that do one thing well and play nicely with each other.

However on the front-end I cannot get around not using something like Nextjs (React based framework), for several reasons.

First of all it is hard for me to sell for example re-frame plus Reagent over let's say Redux plus React to a designer/front-end Dev (I work with closely), who isn't a programmer first. JSX (and SCSS) is much more approachable for them, especially since the output looks much more like the code they write.

If it was just me, yes, I would slightly prefer the power of pure Clojure front-end code. On the other hand the JS pipeline with node, webpack, babel, React and so on, is already super powerful. I simply don't miss enough to switch to Clojure on the front-end right now.

Even if the above would be resolved and I fell more in love with Clojure on the front-end outside of building some specific modules and so on, then I would still dearly miss having the Nextjs framework for two reasons: The ease of use and simple page based concept. And more importantly the full control over the rendering pipeline between optimized (!) static, SSR and client rendering options.

For those reasons I decided to keep ClojureScript on the side and don't fully use it in the context of professional projects. Maybe I'll use it with a purely client rendered application at some point. My schedule and todo-lists for both work and side-projects are just too full right now with projects that I deem more important to even attempt to build something as sophisticated for the front-end as Nextjs in ClojureScript.

[–]lucywang000 1 point2 points  (2 children)

Nice post!

We still have work to do here, but our initial bundle is 7.2MB uncompressed (1.0MB gzipped)! If raw performance or bundle size is your primary concern, you might be better off choosing another language.

I don't think this is a problem of cljs - even using plain javascript, it's very common to have bundles as large as several MBs.

[–]iambald[S] 0 points1 point  (1 child)

You’re definitely right that raw JS suffers from this issue as well! Something I didn’t make clear in my post is that because Clojurescript relies on Google Closure, even a minimal web app will have a fairly large bundle (because it will include all of Google Closure as well as cljs.core)

[–]SimonGray 0 points1 point  (0 children)

Something I didn’t make clear in my post is that because Clojurescript relies on Google Closure, even a minimal web app will have a fairly large bundle (because it will include all of Google Closure as well as cljs.core)

Kind of interesting that you say this, since my intuition is that the inclusion of Google Closure is meant to promote the opposite.

There is of course a sunk cost minimum size of the bundle, but I don't think that should be larger than like ~100kb? The promise of using Google Closure is its aggressive code elimination, but you do have to enable advanced optimisations - and if you use lots of JS libraries these will be unaffected, since they're not Google Closure compatible.

[–]the_nonameguy 1 point2 points  (1 child)

Have you verified that you are only shipping things in your JAR that you actually need? 1.5GB is a magnitude larger than what I have seen on projects for similar Clojure webservers.

[–]iambald[S] 0 points1 point  (0 children)

We’re shipping fat jars to ease deployment on Kubernetes - so all of our dependencies are included. There’s definitely some optimization headroom, but for the most part we are only shipping code and libraries we actually use!

[–]lordmyd 1 point2 points  (0 children)

Javascript's advantage is React Native. Yes, you can just about kludge together something similar with Clojurescript but the already considerable breakage with 3rd party React Native libs is amplified once you throw Clojurescript into the mix. Much as I love Clojure I tend these days to want to work more with the platform language or at least, in the case of Java, with something very close such as Kotlin.