I need to start a new ClojureScript project with the following properties :
I want to write a ClojureScript app that runs purely in the browser. No need for a server. And eventually I want to compile it to a single JS lib in a stand-alone flat web-page.
This app will be dependent on a library which is written in CLJC and is being worked on in parallel. This lib isn’t available on Clojars. I want to be able to pull the changes live from the library’s own project. (Currently this project is in Leiningen). I believe this is possible if my new project is written with CLI / deps.edn. AFAIK this can’t be done if the new project is itself in Lein. (Or can it now?)
I’d like the “livest” development experience possible. Presumably using figwheel. Maybe devcards. Or maybe there’s something new that I don’t know about? I probably can’t expect that changes to the library automatically trigger a reload of the app in development, but at the least I want an easy way to tell the development app that the library just changed so that it will recompile / reload it.
I’m on Linux and my editor of choice is Emacs. But I’m not an emacs power-user.
Given these requirements, what kind of project should I use? Shadow.js? CLI / deps.edn? Is it possible in lein (which I’m most familiar with)? What development frameworks etc? Is Figwheel / devcards still state of the art or do I want something else?
Shadow-cljs + deps.edn seems to fit the bill. Especially with the “not on clojars” situation, deps.edn makes developing with local libraries great. Use the :local/root option to develop the library in parallel and changes will be picked up by shadow’s watcher.
A quick plug for the deps-new SPA frontend template I started playing with to replace lein new re-frame and clj -Tclj-new create :template re-frame in my personal use cases… here
The original of which, the re-frame template, being something I consistently enjoy that does all of what you describe.
So you’re familiar with lein. Have you used clj-new? To use it as a ‘tool’ globally from the command line (invoking something with -T, read more here), you need to install it. Sean Corfield who adapted clj-new from boot-new gives the install one-liner with its current version on its repo.
Invoking clj -Tclj-new create :template re-frame is telling the tool to create a template. This particular template is not directly built-in to clj-new. I believe these are the templates automatically included with the tool. I.e, there is syntax sugar to use them by just typing clj -Tclj-new app instead of clj -Tclj-new create :template app.
The template re-frame does not need to be qualified AFAIR, but creating a template with that keyword is specifically adapting the existing leiningen re-frame template, which is a main purpose of clj-new:
Generate new projects from Leiningen or Boot templates, or clj-template projects, using just the clojure command-line installation of Clojure!
clj-new is typically oriented toward leveraging deps.edn for projects instead of lein’s project.clj. So normally, using a lein template would eschew leiningen’s build system altogether for the native tooling libraries. However, the re-frame template uses shadow-cljs instead of either to develop, run, build your app.
Have you used re-frame before?
I don’t know what scope your web app needs to be but, paired with its great docs, the library helped me learn a lot about structuring web projects in clj/s. However it’s a whole thing to get into lol!
Feel free look more into the differences between leinclj-new and deps-new to get a feel for their differences and how easy project setup is these days… I do not have expertise but I’ll try to answer any more questions
To elaborate a little on :local/root mentioned above, here is its usage in context.
;; deps.edn located in the project root
{:deps {org.clojure/clojure {:mvn/version "1.11.1"} ; syntax and coordinates available per-library on clojars
standard-hosted-lib/library {:mvn/version "x.y.z"}
me/my-local-library {:local/root "/absolute/path/to/my-local-library"}
me/other-library {:local/root "../relative/to/other-library"}
someone/their-library {:git/tag "x.y.z" :git/sha "1234567"} ; coordinates would be provided by the author if available solely on github
;; :paths [...] :aliases {...} etc
}
You can see you just need to supply the coordinates like anything else hosted on maven or git, but using the correct keyword and a dir path.
It’s a really powerful tool and there is plenty of writing elsewhere about the flexibility it provides compared to working on projects with leiningen, I will agree
Oops just note that the syntax would be slightly different here with shadow-cljs.edn as opposed to deps.edn .. Again linked above by @borkdude
I have to say that at this point I seem to have tried half a dozen completely different ways to boot up a new reagent project with clojure.tools, following various instructions / tutorials I have found online.
AND EVERY ONE HAS THROWN AN ERROR SOMEWHERE.
I CAN’T BELIEVE how bad and difficult it seems for a non expert to start up a new Clojure project these days.
In 2014 when I first got into Clojure, it was beautifully simple and straightforward using Leiningen. It just worked and I was programming within an hour!
WTF???
How have we all managed to make this whole thing infinitely worse in the last 10 years? More confusing! Layers of brittle dependencies! Dozens of outdated tutorials! New tools all of which explain I need the latest version of some other tool I’ve never heard of.
I’m genuinely shocked. How does anyone get started with Clojure these days? If it had been this hard back in 2014 I’d probably still be writing Python.
How old is your Clojure version? I’d say first make sure you have the latest version of the JDK and Clojure, which you can do if you have brew like so:
Yes precisely. I was going to say it should be all of three to five commands to go from nothing installed to a project not only installed but running in active development.
I use jenv to manage which jdk I currently have in operation and if I run into mystery issues I’ll often just jump back and forth between, say, graal, openjdk or oracle just for kicks.
I feel like these odd issues just come down to something going wrong with some link in the chain. Which making sure versions match and software is installed properly generally fixes.
I don’t believe that’s it. 1.11.1.xxxx will all fall under the same 1.11.1 version when declaring dependencies per-project
You could still use brew on Linux, that’s what I do as well, I’d recommend it, does make a lot of things easier when there’s isn’t always official Ubuntu repo packages for all the things. Just FYI: Homebrew on Linux — Homebrew Documentation
What happens when you run:
clj -version
The Clojure CLI is pretty new, and things were changing quite quickly, so ya, even a minor version could have added the tools supports.
I would also try:
clojure -T
Don’t type clj, type clojure. I’d be surprised, since both work for me, but I’m currently on a mac, so maybe rlwrap does something weird for you.
Otherwise, there’s something wrong maybe with your install.
Also, if you don’t want to learn how to use the new official build and deps tooling and Clojure command line, you can still use lein, a lot of people still use lein. You can at any time in the future choose to learn the new stuff and migrate your project to them.
clj -version
WARNING: When invoking clojure.main, use -M
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
-version (No such file or directory)
Full report at:
/tmp/clojure-2320301461189067898.edn
Meanwhile
clojure -T
-T is no longer supported, use -A with repl, -M for main, or -X for exec
clj -version
WARNING: When invoking clojure.main, use -M
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 > (FileInputStream.java:-2).
-version (No such file or directory)
Ok, can you just try uninstalling and re-installing?
Something is definitely wrong on your side.
Did you alias clj in your shell to something specific?
I’m sorry this is frustrating because I sympathize when trying to start an effort seemingly fails for me before I can even get to step 1! It’s happened to me a lot. I hope you can get it dialed in because I’ve found the fruits of developing in this environment so rewarding.
I personally am absolutely no expert with any step of software development. Let alone the complexities of this language which has struck me from day 1 as advanced! But major steps have been taken by a lot of hands to smooth out the sharp corners.
These errors look really unusual and unrelated to any of the project tooling we’re discussing here. I’d emphasize reinstalling fresh. I also advocate for homebrew on unix-like systems.
Specifically with the section entitled “Installation via deps.edn”
In that directory I had made a deps.edn file based on his suggestion there. And when I ran
clj -Mtools
I got
clj -Mtools
Clojure 1.11.1
user=>
But actually when running the same thing outside that directory, I’m seeing
clj -Mtools
Clojure 1.10.1
user=>
So maybe I only have 1.10.1 installed “globally” and I was being misled by trying some of the things in that local context that was defined by having that deps.edn in the directory.
This would probably explain some of the mystery.
So, OK, what I need to do is to update Clojure cli.tools from 1.10 to 1.11
Is there really no way to do that except using homebrew? I don’t really want to bring yet another package manager into my life, as I already seem to have way too many.
But I assume clj doesn’t know how to upgrade itself then?
I think I must have used that the first time I installed clj.tools, but at some point afterwards I must have allowed Ubuntu’s package manager to take over.