ClojureScript Year in Review
swannodette.github.io
swannodette.github.io
Not to mention that REPL-driven development and hot-reloading are so pleasant to work in, leading to development environments like this: https://github.com/danielsz/holygrail
I'm curious if any Clojure veterans would weigh in on the state of Boot.. is it gaining traction, or is the consensus to stick with Leiningen?
I've been using boot for smaller and experimental projects because by default it feels so much leaner then leiningen does, however, because the support tooling around leiningen is still so further advanced, for project we're putting into production here, those are still all lein based.
The other thing I'd say is, I've found what tool lein vs boot gets minimized over time as the project evolves.
In general, I do think it's gaining traction and its a great project!
This all seems really exciting for Clojurescript. To me, it seems like it is a good option to have code that runs on multiple architectures. The ecosystem was lacking in some basics though, especially interacting w/3d party JS libraries, and I think CLJSJS (or something like it) will probably be one of the most important things for Clojurescript.
Seems like there's a decent quickstart on the Clojurescript github wiki (https://github.com/clojure/clojurescript/wiki/Quick-Start), is there a good next-steps resource that's current?
Here's my 2 cents - Cursive is worth it. (Hey Ideogram folks, if you want an endorsement, feel free to use that paragraph in exchange for a lifetime license ;)). For one-off-scripts, for back-end solutions, and what tipped me over the edge, it's CLJS script integration goes beyond acceptable -- it's actually fun to work in-- Cursive is my go-to. Om and Figwheel (optionally with Prismatic Schema if you like type guarantees) makes web development's feedback loop a lot tighter.
Rich Hickey assembled a team of just insanely talented and charismatic(1) developers who not only are a) remarkably intelligent but b) know when to steal ideas and integrate them [none of that too-proud-NIH-syndrome there], and c) know how to interact in a way to that is community-feedback-positive(2) so people contribute. Watch this talk by David Nolen https://www.youtube.com/watch?v=ByNs9TG30E8 (CLJS lead). [Sidebar - He even mentions how that whole immutable, one way data flow, datomic-ish single state idea existed in other languages, but read (2) on that].
Anyways, Cursive + Lein + ClojureScript + Om is the holy grail for me right now. On the other hand, that nREPL/cider/boot setup is what I'd be using as a long-time emacs'er were I to give up Cursive.
(1) Having someone like Hickey or Nolen to shepherd ideas is actually really important in garnering traction. Developers go to conferences and when everyones talking about that 4PM Thursday talk that someone gave, it really resonates within the community for quite a while. I like Perl 6's ideas but if you've ever seen Larry Wall talk, well, yeah. (2) Some communities cough Haskell have great ideas, Lenses, FRP, applying (pun not intended) monoids -> functors -> applicative functors -> monads was genius. But for some reason the barrier to entry is so high (even for me with a fairly advanced math background) that concepts remain isolated within the community. LINQ is a monad (though few know it) and it took Brian Beckman (or Anders, or Bart de Smet, or whomever) to take it into C# to make the concept widely used by the Joe-the-programmer (again, pun not intended).
Well, I'd hate to be accused of buying positive reviews :-). But thanks, I really appreciate it and I'm glad it's working well for you.
One of my main goals for 2016 is to focus heavily on CLJS support to bring it fully up to par with Clojure support. Better REPLs, a much easier getting started story, testing support, a debugger, and as much support as seems to be required for React Native. I'm increasingly convinced that CLJS may turn out to be more important than Clojure, and certainly has the potential to bring a lot more devs to the CLJ(S) world if it manages to take off properly.
One of my main aspirations with Cursive is that it can help make both languages more accessible. I think Clojure support in Cursive is further along that path and I'm hoping to do the same for ClojureScript this year.
I've contemplated learning Emacs because of the general praise for its workflow in the Clojure community. I even know some basic emacs from bash scripting. Switching just seemed like it would add another learning block to an already long list of tools to learn. Cursive, on the other hand, is based on IntelliJ, which is familiar to me through RubyMine.
Thanks for taking the time to write up about Cursive. You just convinced me to finally install it and give it a shot.
But to get up and running and try things out? Use Cursive until you are comfortable, don't get distracted by tooling problems (which there will be).
Install OpenJDK: http://www.azul.com/downloads/zulu/
Install Leiningen: http://leiningen.org/
Create a new project and run it:
lein new reagent myapp
cd myapp
lein figwheel
This will start the live ClojureScript compiler and your app will be available at localhost:3449
You can now navigate to the src/cljs/myapp/core.cljs file and start editing it. Any changes you make will be reflected live in the browser without having to reload the page. I recommend trying the code from the Reagent docs page linked above in the project.
Especially when you bring in concepts like generators [1] (as a replacement for clojurescript's async), destructuring,etc.
First off, cljs allows you to type less. Second, functionality provided by Immutable.JS is built into the language. Third, I can use paredit. I love paredit. Fourth, google closure has amazing code minification, dead code removal and a good standard library. Fifth, I've found figwheel to be better to react-hot-loader, the latter cannot always reload my application. Sixth, devcards. Seventh, incremental compile speed is faster. Eight, macros can greatly simplify code you're writing and allow new syntax to be exposed by libraries (core.async).
But it seems that 4 out of your 8 points are covered by external libraries that are pretty good - Immutable is great... lodash is great... and google closure compiler is usable (https://github.com/mihaip/react-closure-compiler). I use systemjs/jspm as well as its hot reloader and it works great (unless a particular component is legacy JS.. which will be a problem anywhere).
Not really refuting your point, but ES6/ES7 (and from what I'm hearing.. Typescript) with all these libraries have sort of taken over the mindshare that clojurescript used to have.
IMHO the only reason for me would be the package manager. I mean Systemjs/jspm is okay.. but the whole AMD/global/cjs/webpack/requirejs/browserify crap is way too much. Nothing works anywhere in the javascript world .
Immutable.js is great, but your libraries probably doesn't use it, and you have to make sure you use it everywhere as well. This can lead to subtle bugs that boils down to using .value instead of .get('value'), a problem you'll rarely encounter in cljs where everything is immutable by default.
I haven't used systemjs/jspm, so I can't say anything about that. I can only say that I have yet to encounter a case where figwheel doesn't successfully reload my code, whereas I encounter this in webpack/react-hot-loader all the time.
ES6/ES7/Typescript are great improvements over ES5. But you have to pair it with Immutable.js for it to be comparable to the offering that cljs provides. Even then, when you have a setup that gives many of the same benefits as cljs, you'll have written way more code, and you need to be a bit paranoid to make sure you're using the correct API at the correct place, and that you don't have any libraries that are incompatible with your setup.
In short. While you can have a setup that gives you all the advantages of cljs+om/reagent, it's just a lot easier to do it in clojurescript.
But that's precisely my point. Is there value in a pure language when you will need to leverage tons of third party libraries...most of which are incompatible? To get anything meaningful done, you would need to write EVERYTHING in cljs...or you could use a component which will be in old js. So where's the tru value of cljs in a real life project.
Let's take Handsontable - to cover all the corner cases that a spreadsheet needs, it would take me an inordinate time. But it does not even play well with npm..forget cljs
Clojurescript and Clojure have very good interop with their host language, integrating 3rd party libs is very simple. To be fair, you will have to write the glue code more often than when working in js since there is a smaller user base.
And now that you mention it you have jogged my memory about having to sidestep our build process in some unfortunate ways. We're certainly not passing it through Google Closure, we have to use the handsontable build scripts to remove unused features.
Getting it to co-exist with React was the real tricky part, but Rum was quite useful in providing the hooks to make handsontable act like a react component.
Thanks for trying.
It's better to have a problem with some dependencies, than to have an issue with your entire codebase. So yes, I would argue that clojurescript has value.
I found this joke on r/ProgrammerHumor and it strikes me that I've been falling into this trap for the majority of my career.
> You know what we need? Another mostly imperative garbage collected language, that's what. If we just tweak the syntax and feature set just right, it will change everything!"
As Skinney writes, the mix of libs and tools that you base your webapp on might not be what the libs you want to use the next months agree with.
Use of immutable collections are nearly pointless if only parts of your app use it, and you have to carefully maintain barriers that translate to/from them. Clojure(Script) makes their use succinct and natural, something I doubt yet another lib can make ES2015/TypeScript do.
The biggest problem with ES6 is that JavaScript just keeps growing as a language. It has lots of features and quirks already, and more are getting added. This is what you end up dealing with when using ES6 + React (https://i.imgur.com/AjSTP20.png).
I think the problem with this is that it adds mental overhead when you're reading and writing code. Something that looks like it might be doing one thing does something subtly different. This leads to hard to debug errors and wastes you time. It also distracts you from the actual problem you're solving.
I also find tooling for ClojureScript is better in many areas. Instead of having to juggle things like npm, gulp, grunt, and so on. You can use a single build tool like Leiningen that handles all those things. You have a live coding environment with Figwheel, and you get an editor integrated REPL where you can inspect things easily at runtime.
I've been using ClojureScript in prod for about a year now without any issues. I simply wouldn't go back to using Js at this point.
https://github.com/reagent-project/reagent-cookbook/blob/mas...
You will want to understand how pods and filesets work if you are doing anything interesting, as some interactions with them can be confusing if you don't have the right mental model. The wiki is quite good, but the source is a bit messy.
For code reloading type tasks things are bit less nice, mostly because of the immutable nature of pods and filesets that make build tasks so trouble free. That means incremental cljs compilation, cljs repls and auto-test type tasks (for clj and cljs). We have transitioned to just using functions run from the repl to manage our clojurescript tasks and it has been a big improvement.
From straight up confusion to basic productivity in just a week, it has also completely removed the learning fear. Highest regards to this beautiful tool that will hopefully bring lisp to the masses.
My one complaint with cljs has been the difficulty of configuring Ring HTTP beyond the trivial SPA defaults: getting it to respond to other URL requests, other types of HTTP requests. I spent close to 3 hours trying to configure it to accept a POST action before finally giving up, frustrated by the opaque stack traces that went >1000 frames deep. 20 minutes later, I had an Apache server up and running. So it wasn't really a big deal, but I can't remember the last time I felt so baffled by a problem that I simply had to throw in the towel.
I'm just curious because my only exposure to the HTTP layer so far has been via Apache. Apache is... for lack of a better word, a bro. It's up for just about anything. It seems like the default mode of Apache is to do whatever the HTML recommends. Apache is happy to serve an arbitrary "/about.html" URL, provided it exists, and asynchronously execute any server-side scripts to which it injects a dependency. I don't know if this strictly requires the use of jQuery, but it certainly seems easier to do it that way. Is it even possible to serve a cljs app this way? In light of the fact that jQuery is not compatible with the Google Closure compiler?
As far as self-compilation, I haven't seen anything on how to compile a ClojureScript project without Java, is there an article somewhere on how to do so?
here's how to bootstrap cljs.
Has no one distributed such a cache in a way that it's easier to do a compile without Java installed? Is there not anything as simple as (where cljs-compile is a Node script):
cljs-compile file.cljs > out.js
yet?On the other hand, I have never really seen a need to remove it. Once the CLJS compiler is up and running, incremental compilations on huge codebases (~300 files) takes a fraction of a second. So in the end...I'd rather have the JVM as a requirement if it allows that fast of a dev cycle.
But over all, no matter what you use, core.async, or callbacks or whatever, limit the async bits to the edges of your code. Done correctly (Om.Next is a great example) you shouldn't need a whole lot of async bits to get a nice clean app. If you have core.async "go" blocks littered all through your codebase, you're doing something wrong.
But I guess I always get hung up on the idea that you should just write in the language that you're targeting, and I wonder about the cost of the (admittedly pretty nice) developer experience of cljs. When you have a bug in production you're stuck debugging the generated JS. This was also my problem with CoffeeScript.
Debugging story is very good. You pretty much never have to see the generated JavaScript. ClojureScript uses source maps, so any errors in the compiled Js will map back to the original ClojureScript source that caused them. Chrome dev tools even do syntax highlighting for ClojureScript now.
Having a live dev environment with Figwheel and a REPL goes a long way here as well. You can inspect a lot of things at runtime very easily.
Using immutable data structures by default avoids a lot of the debugging pain as well. You practically never have to trace through a bunch of function calls to find the problem. In most cases the problem is exactly on the line where the error occurred.
These do a great job of handling the platform specific quirks for you. The first app I developed with Reagent actually had to run on IE8, and to my shock and surprised worked without any issues after I added the standard IE shims.
So, overall my experience is that you're better off dealing with IE than with most Js frameworks.
Clojurescript, and core.async in particular, changed my mind. It has converted me completely. The debugging issue is much less of an issue than I expected, since other methods of problem solving make more sense in a clojure context than breakpoint style line by line debugging.
Of course sometimes you do need to drop to that level, and it is a bit of a learning curve to debug the generated js, even with the great source maps, but it's not that bad. Overall I am still more productive by a big margin, and it's more enjoyable.
I've been working on Dirac - a Chrome DevTools fork for ClojureScript developers. That will be a complementary tool to cljs-devtools: https://github.com/binaryage/dirac
You also get a clean and well designed language as opposed to a mountain of kludges that is current state of Js https://twitter.com/capotej/status/677926991513780225
I build the first version of my app with cljs, and it was the cleanest/simplest code I ever wrote. Just the lack of npm interoperability makes in non-viable for me.
Anyone tried systemjs with cljs?
It is by default slower than Java and Go because the default data structures are immutable. When execution speed is more important than statelessness you can make your data structures mutable.
Read more about that here http://clojure.org/transients
Happy holidays :)