Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
ClojureScript 1.10.741 (clojurescript.org)
265 points by Jeaye on April 25, 2020 | hide | past | favorite | 67 comments


To the entire ClojureScript team: thank you so much for all the great work that you are putting into ClojureScript!

Without ClojureScript and Clojure, I would not have been able to build and maintain my SaaS app as a solo founder. The incidental complexity would have crushed me. Using a single language to write code, with model (domain) code effortlessly and fluidly shared or moved between "server-side" and "client-side" is a game-changer.

While I don't care that much about NPM, I am extremely happy with the progress that ClojureScript is making. Thank you!


i feel you, jwr. at my previous startup i've developed everything with clojurescript. our dashboard, our browser plugin, our react native app was all cljs except for the api which i built with django.

thanks to clojurescript, i was able to build all these tools so fast and clean, we had a lot of time to work on the business itself. we failed to find a product market fit though.

to every new founder out there who always wanted to try clojurescript, if you are going to work on a client application and love react, i cannot stress enough how easy and fast it is to develop with clojurescript and re-frame.


How up-to-date is clojurescript+react-native workflow?

I checked Re-natal as tool to manage build/debug workflow with clojurescript+react-native

https://github.com/drapanjanas/re-natal

But re-natal supports up to React native 0.59, which is quite far back, in the RN-release-years time units.

Now React-native is 0.62.


You can also check out shadow-cljs which has great support for React Native development. I've been able to easily keep my project up to date with the latest React Native versions. Plus with shadow-cljs you also get access to all of npm in a very straight forward way.


i'm seconding this. not only react native version that re-natal supports is old but also the re-frame & reagent versions it supports are pretty old. shadow-cljs is really a good solution and you can pick it up for react-native projects too.


If you want to use this new Clojurescript workflow with React Native, check out Krell: https://github.com/vouch-opensource/krell


I like reading these kind of stories.

I'm trying to learn more about Clojure / CLJS for web development specifically, but there are so many different tools to pick from and as a beginner it can be hard to know where to start.

And then I'm also reading about Phoenix (Elixir) and how that's better for web dev.

If you don't mind - can you tell a bit more about your Clojure story, when you started using it and your setup?

Or maybe you have a blog, where you wrote about this already?

I'm not an experienced programmer, hence the naive questions.


The Clojure way of doing things is mostly about composing different libraries for your needs. You will have a lot of small tools to work with, and comparing to Phoenix, doing even the easy things take more effort to write code. Phoenix gives you a full framework, bells whistles and all, but you have to work within the constraint of the framework.

If you are an inexperienced programmer, you might want to just stick to Rails or Django, tooling and standard are easier to learn from those frameworks, and their shortcoming aren't visible to you anyways.

If you just want to learn programming for fun, or at the start of your path trying to be the best programmer as you can be, Clojure is a valid option, but there will be a lot of head banging around the code.

Tldr; clojure = more exotic, weird but great features, you should be comfortable rolling things on your own, elixir/phoenix = more exotic rails, stick to rails if you just want to make a website.


RE: start of your path trying to be the best programmer as you can be

Thanks. Nicely put - that sums it up.

Back in the day - over 10 years ago - I was a hybrid designer who also coded up his own design (JS, Actionscript, PHP) but then focused more on design & product consulting. I want to build stuff again and I want to learn this craft properly and hence why I'm attracted to both Clojure and Erlang / Elixir.

I think it's important to choose good (virtual) mentors and Rich Hickey / the wider Clojure community and Joe Armstrong and the Erlang / Elixir community seem to be great communities with smart, thoughtful and considered people.


Clojure/Script is more geared towards experienced developers who want the power to do whatever they want, in a conscise, expressive and customized way. They value flexibility, and immediacy, and like to know all the ins/out of their tools.

Elixir is a version of Clojure adapted more towards the Ruby model of making things easier for developers, giving people more focus, less choices, emphasising best practices, and overall offering something more familiar looking to most. It's complemented by Phoenix, which has similar goals, it is focused, directed, gives people a clear path forward.

They're both capable language, but you can see they have different focus and are geared towards people looking for different things.

So it depends what you're interested in:

If you like to do things from "first principles", meaning, you want to understand starting from birth and grow to adulthood, then Clojure/Script is for you.

If you prefer to do things "on the surface", meaning, you want to just get going with a project, see something get build fast, before you understand exactly how it all works, i.e., you want to start from adulthood, and slowly (or never) make your way back to the birth, then Elixir/Phoenix is for you.


I don't think your description of Elixir and Phoenix is correct: Elixir is a language targeting the erlang virtual-machine. it does not seem clojure-inspired. Phoenix is a web development framework written in Elixir.


From the creator of Elixir (Jose Valim) himself:

> I’ve learned a lot also from Clojure because, at the time I was thinking about Elixir, Clojure was already around. I like to say it’s one of the top three influences in Elixir

[...]

> The main, the top three influences are Erlang, Ruby, and Clojure.

[...]

> I was like, no, but I’m going to call them protocols because there are a lot of similarities between Clojure and Elixir in terms of them being dynamic languages and in terms of the macro system. I was like, okay, I’m going to call them protocols because the closest thing we have today to what I want is Clojure

And he goes on talking about more inspiration and similarities from Clojure like Agents, etc.

Full exert is here: http://blog.cognitect.com/cognicast/120

Edit: Ah I see where you could have gotten confused. By "version of Clojure" I meant in that it is very similar and has taken a lot of inspiration from it. Elixir isn't an actual dialect of Clojure the way that ClojureScript and Clojerl are. That's not what I meant to imply. Having used both language, they do share a lot of similarity in design, with most of the differences being Beam/Erlang vs Jvm/Java, and Elixir pulling more from Ruby, while Clojure pulls more from Lisp. This is what I meant by "a version", I should have said "is like Clojure, but..." instead I think to avoid this confusion, but too late for me to edit now.


The way you use them and how you model the world with them seems very similar to me


I'm building my startup in phoenix.

First of all I wanna say that Clojure is a fantastic language and if the dials on my particular needs were different, I would have gone with Clojure and am considering clojurescript for a subproject paired with an elixir backend.

When I started the project, realtime over WebSockets were a huge consideration. Additionally, we weren't doing anything revolutionary from a computer science perspective. Phoenix came in with a clear story for all the work I wanted to accomplish.

There were well accepted and documented libraries for doing authentication and a really nice library for accessing the database.

The language has few gotchas and is relatively easy to learn. I have no doubt I could take a good js or python developer and have them be proficient within 2-3 weeks. Thats a big deal for when we are ready to onboard more people.

The elixir language feels a lot like clojure with a ruby like syntax. you have maps(structs) and a similar theme of 100 functions on one data structure. When sketching an idea, I can build my data structure out as a map and delegate to functions based on specific properties within the structure just the same as you would in Clojure. The language supports hygenic macros though I have been content with using the ones provided by absinthe and the kernel.

Phoenix itself is Extremely composable. Yes there are some constraints imposed by the language but no where near what you'd find in a more magical framework like ruby. In every case I've run into, I've been able to granularly pull and modify whatever functionality I've needed. middleware for instance is oriented around plug. Plug consists of a struct that contains data pertaining to the http request and response. ALL middleware is a function that takes a plug struct and returns a plug struct. Its about as composable as you're going to get. The end result is a very stable system that is really easy to reason about.

The biggest advantage, however, has been the deployment and infrastructure story. OTP is fantastic and lets us create workers about as easily as you could create a controller in rails. This is big. for our mvp, we don't need to setup redis or rabbitmq nor deal with the headaches of configuring them in prod. I can create a pubsub worker that responds to events and broadcasts data to the users in real-time and stay completely within phoenix.

Of course it has its downsides. For one, its definitely not my language of choice if I was doing image processing or constraint solving. At some point, we are going to create other microservices that handle those kinds of tasks better and when it happens, we'll have to pull in rabbitmq or kafka. Obviously phoenix can't have isomorphic apps like you would find with clojure and javascript.

TLDR: if you're trying to do something really novel, go with clojure. Its a much more flexible language with some really neat libraries that you'll need to learn to integrate yourself. If what you're doing is CRUD but with realtime, elixir will give you a great base ecosystem with sensible defaults to get off the ground fast.


There is another type of application where Elixir/Erlang really shines. The most obvious example of this type of application is a web based game where you have thousands of instances of the game running at once. The concurrency and isolation model is pretty much a perfect fit for this.

I was trying to hack something together in Java that wouldn't kill the database. Queries to table x would bottleneck, then table y. Add some caching here and there as each problem cropped up. But the obvious design in Elixir just removed most of the problems - each instance of the game works as its own set of processes and each instance holds what it needs in memory. It's not that I couldn't have arrived at this model with Java eventually, but it doesn't exactly lead you there, and a language like Elixir/Erlang was basically built with this in mind so everything is a lot easier to accomplish than with something like Java.

I really think everyone should learn either Elixir or Erlang. There are certain applications where OTP and BEAM just makes everything so much easier than the alternatives. If you have the right problem it can be an insanely productive language.


I had one case where I needed to store account data and ended up storing it in a gen server object for each account which pushed its state to all devices logged into that account. It was so easy to build I forgot about it but this 4-hour project would have taken over a week if I had done it in any other language.


Thanks for chiming in.

It helps to better understand the use case for each language.

I like the way you put it: Elixir = CRUD but with realtime.

Maybe I'll end up learning both, but have to start with one.

Hey and good luck with your startup. It reminds me of what PG wrote about - i.e. choosing the right tools to build your business matters [0]

[0] http://www.paulgraham.com/avg.html


You'll actually find it pretty easy to learn both. Elixir was very inspired by Clojure, so it works similar to it in a lot of ways. It is like taking Clojure and removing the Lispy aspect from it (which to me is the biggest downside of Elixir, as I love Lispyness, but that also makes it more approachable and familiar to people without a Lisp background).

The biggest difference will actually lie on the host platforms. Learning BEAM and Erlang standard library Vs learning JVM and Java standard library.

For complenetess, I want to point out there is also a Clojure variant running on BEAM/Erlang called Clojerl found here: https://github.com/clojerl/clojerl

Development is pretty active, and I think it is approaching maturity pretty soon.


> When I started the project, realtime over WebSockets were a huge consideration. Additionally, we weren't doing anything revolutionary from a computer science perspective. Phoenix came in with a clear story for all the work I wanted to accomplish.

Incidentally, my app uses websockets and real-time updates based on RethinkDB changefeeds.

But more to the point of this thread, one of the major advantages is that I use a single language for both client-side code that runs in the browser and server-side code that runs in a JVM. Same language, same data structures, no impedance mismatch, no crippled transit format. All the domain code is shared between both environments.



This link explains the new Webpack support in more detail: https://clojurescript.org/news/2020-04-24-bundle-target

Though that post is pretty good, I wish someone could create a more ELI5 version of the post for people who aren't knee-deep in javascript packaging systems. Can someone just answer some newb questions for me?

1. I know there's a website where people store javascript packages in "npm" which can be viewed here: https://www.npmjs.com/package/browse. Does this new clojurescript functionality let me USE all those packages in clojurescript? What are the precise limitations? In what cases do I still want to use cljsjs? (another thing that is confusing to me, tbh)

2. Does this new clojurescript functionality let me CREATE new npm packages and put them on the main npm site? What is "webpack" exactly and how does it relate to npm? If so, what are the precise limitations?

I swear I know a fair amount of stuff on other programming subjects, I just have a blind spot when it comes to javascript packaging and packages, so this info is really appreciated!


1. NPM is analogous to Maven for Java. Yes the ClojureScript bundler target lets you use anything you've installed from NPM into your project's `node_modules` directory. Not many limitations because we wash our hands of dealing with this stuff - use whatever popular bundler solution you prefer.

2. Not for creating NPM packages, just consuming them. Webpack lets you use dependencies from NPM and package them up into a single JS (or code-split) asset to be used on a webpage. Note, we have no integration to any particular bundler. You could just as easily run Metro for React Native on the output and build a mobile app.


Have you considered Parcel, going forward? It seems to be a lot lighter and easier than Webpack.


We have no specific integration with Webpack, so you can consider anything since we haven't chosen for you :)


Thanks, that clarifies things a lot!


Caveat: if you want your code to run in a web browser, you will need to be careful about which npm packages you use, since some are server-side only.


There's also a relatively straightforward guide to usage with Webpack here:

https://clojurescript.org/guides/webpack


> Does this new clojurescript functionality let me USE all those packages in clojurescript? What are the precise limitations?

If you use Shadow CLJSs (all-in-one tool for ClojureScript), you've been able to use NPM packages directly for many years now.

> Does this new clojurescript functionality let me CREATE new npm packages and put them on the main npm site?

Shadow CLJS also lets you create NPM packages.


> If you use Shadow CLJSs (all-in-one tool for ClojureScript), you've been able to use NPM packages directly for many years now.

That's not only true for Shadow CLJS but ClojureScript in general have allowed you to use npm packages for many years as well, although it was a bit clunky. Shadow CLJS did improve the developer experience though.


Somebody please write a book on Clojurescript, reframe and tooling -- its about time. There are so many books on Clojure but very few on Clojurescript and most of the existing Clojurescript books are too old and have not kept up.

I prefer learning new languages by reading books about them.


This is the book you're looking for: https://www.learn-clojurescript.com/

I've been keeping tabs on it and progress is being made all the time. Already tons of content.


Web Development with Clojure (3rd edition) comes out later this year. It's got both Clojure and ClojureScript in it. In fact, even Clojure books that aren't focused on web development tend to have a ClojureScript section in them.

ClojureScript Unraveled is being updated continuously and is available for free online: https://funcool.github.io/clojurescript-unraveled/

But honestly, you can use Clojure books to learn ClojureScript too. They're basically the same language, with a few minor differences based on underlying differences in the hosts (JS and JVM). I tend to write most of my code in CLJC style, which can be compiled for either platforms.


The complexity with Clojurescript is in the tooling ecosystem. With Clojure , you only have the repl. However, with clojurescript, your have figwheel, shadocljs etc etc. I gave up on setting that up correctly with my IDE( Visual Studio).


Shadow CLJS is very easy to set up and there's a whole book's worth of documentation: https://shadow-cljs.github.io/docs/UsersGuide.html

You don't need figwheel (or any other tool) if you just want to write ClojureScript. You can get a ClojureScript browser REPL like this (mac example):

   brew install node

   npm install -g shadow-cljs

   shadow-cljs browser-repl
I get that it's going to be hard if you want to integrate stuff into an IDE that doesn't support ClojureScript. I use IntelliJ with the Cursive plugin (free version) and use `deps.edn` for dependencies since it's supported directly in Cursive.


Visual Studio? First time I hear someone using that for Clojure/Script. Do you mean VSCode or the full on Visual Studio?


Reading about cljs I ended up watching some videos on youtube. I for one didn’t know cljs is so fun: https://m.youtube.com/watch?v=VbIawuoYAVY



Really good. Notebook like Env.


If Clojurescript can actually work with Webpack and external modules under advanced compilation that is pretty amazing progress. Probably the biggest improvement in half a decade.


Unless I'm misunderstanding the ClojureScript team posts, one of the motivations for tight webpack integration is that not every npm module is compatible with advanced compilation.

From the article[0]:

> But after nearly three years since we first shipped Node module processing via Closure, it’s apparent that too few of the most popular libraries can be subjected to advanced optimizations. While we still believe there’s promise here, the ClojureScript community will have to show the rest of the world the way by developing compelling JavaScript libraries that can be readily consumed by popular JavaScript tools, yet still be subjected to Closure’s phenomenal tree shaking and code splitting when building with ClojureScript.

0: https://clojurescript.org/news/2020-04-24-bundle-target


Is this likely? Clojurescript comes with a pretty big base bundle size due to the runtime, right? Like hello world is still over 100kb or something before gzip, right? (On my phone, so it’s hard to google the exact number.)


That was a bug. It was fixed with this release, and swannodette added a test to ensure the size stays under 10k bytes: https://github.com/clojure/clojurescript/commit/5d64c2a142e5...


Swank! That’s a massive improvement. I’m going to spin up a Preact project and see how it fares.


Can’t shadow-cljs already do that, or?


Yep. But having this feature only in shadow-cljs doesn't do much for the ecosystem as a whole since non-portable. With this change, many tools, cljsbuild, Figwheel, etc. have the same capabilities. It also opens the door for creating ClojureScript libraries that depend on node_modules and these can again be consumed with any tool.


Thank you so much for all of your work on ClojureScript, @swannodette!

I love the work that's been done on shadow-cljs (and the maintainer is amazing) -- I've had a vastly easier and more stable time than with JS bundlers.

That said, in building a business on top of Clojure(Script), it's incredibly reassuring to know that shadow isn't a single point of failure.

This feature will make integrating/selling ClojureScript into existing projects easier too -- I only wish that I'd had this when moving from company to company a few years ago -- I'd have brought ClojureScript to a number of places. :)


@swannodette In the library case does the cljs built library need a clojure runtime bundled? Or does banning eval and running it through Closure allow for only the bare minimum to be pulled through?


Just wanted to pile on the thanks, too. CLJS spoiled me for just about any other way of doing front end work.


Thanks David, that sounds pretty great!


I've been really thinking about using a functional language that complies to JS to start to learn more FP concepts and paradigms. I'm trying to decide if ClojureScript or ReasonML is better for me. Anyone have experience with both?


Both are beautiful in their own ways. I think ReasonML, or even SML or OCaml might be a gentler introduction since they let you write imperative code (more closely to what you probably write already) whenever you need to.

For example, I think there is a gradient from OCaml > Clojure > Haskell about using mutable data structures in your code, from Encourage > Discourage > Disallow. I think learning Haskell as your first FP might turn you off given how strict it is in this regard. So using that as a line of reasoning, using OCaml or ReasonML might be best since it lends an imperative hand whenever you need it, and lets you explore all of the amazing things FP has to offer.


As a counterpoint, Clojure is considerably more permissive because it is dynamically typed:

CLJS has some warts due to the compiled JS being hard to understand (use source-maps) and the Clojure error messages being bad is now a meme but if you've not dealt with a Hindley Milner type system before, Clojure can help you learn some of the other basic FP concepts in a more gentle way.

I think it comes down to what you want to learn from FP and where you're coming from:

If you want to just "build stuff" and make it "more functional" ie using lots of data/values and passing around functions maybe go with Clojure.

If you're interested in how static types can make things easier to build more robust things but you only want to dip your toes into FP go with OCaml/Reason

If you want to see what it means to program 100% pure and have no side-effects (and you're willing to invest in learning and delaying instantly "shipping" something) go with Haskell/Purescript


I don’t know. Having used both, JS to CLJS was a much easier transition for me than JS to Reason. CLJS makes mutation pretty trivial if the thing you’re operating on is a JS object.


There are built in mutable data structures now too: https://clojuredocs.org/clojure.core/transient

Though their usage in public interfaces is not idiomatic Clojure and they come closely coupled with functions to transform them back to immutable values.

You can look up eg TransientArrayMap in ClojureScript internals to see how it's implemented on that side: https://github.com/clojure/clojurescript/blob/799d62fe3bba99...


I wouldn't say Ocaml encourages using mutable data structures. You have to use a ref to have a mutable variable. Most stdlib data structure are not mutable (operations on them return an updated structure.)

Perhaps Common Lisp is a better example of a language in that part of the functional purity spectrum ?


I can only speak about clojure. It is a very simple, very well designed language.

I don’t know ReasonML specifically but one core difference to typed FP languages is that Clojure is less obstructive generally speaking.


Perhaps PureScript as well.


Does this enable the possibility of having ClojureScript loaders for Webpack?

Shadow-cljs is great, but from time to time, it seems to be easier to integrate with the ecosystem if it can be loaded as Webpack modules. For example, loading arbitrary image, file, and possibly Rust modules, etc.


Honestly not sure, I'm not a Webpack expert and have no wish to be :) But again, as I've said elsewhere, there is no specific integration with Webpack. The bundle feature makes no choices so it's easier for users to fully control the integration with any JS build tool.


Thank you for your response! ClojureScript is by far the best target-to-browser solution I have used. The REPL experience is stunning, macros work as expected, and Cljc compilation is seamless. Working with it is pure joy.

Thanks again for everything you did for ClojureScript, and your talks are also really inspiring!


Probably not. I'm not an expert either but have some basic experience on transforming my own [script](https://github.com/Cirru/cirru-script-loader) with a loader of webpack.

Normally Webpack loader transforms a single file to another file, like CoffeeScript to JavaScript, mapping one to one. So when it's processing a single file, the loader probably has no knowledge on other files. When it's importing another module, it's Webpack detecting there's a `require` or `import` and revolsing that file.

This solution is not working for ClojureScript. I thought it was thheller told me that ClojureScript has macros, it's not just transforming files one by one, which is not how I was taught to write a loader...

There might be some solution but could be tricky. At least we still need a ClojureScript provided by JVM, which is already a lot more sophistached than a normal Webpack loader.

(I was told WISP has macros like Clojure but transforms with Webpack loader. Didn't investigate into that: https://github.com/girvo/wisp-loader/blob/master/index.js#L1...) .


This is an exciting release. Congrats to the team for their continued efforts and for being such great stewards of the language and ecosystem.

I did have one (orthogonal) issue when following along with the tutorial linked in the release notes and, since there's a decent chance someone here has worked through this same issue in the last few days, I'd like to float the question: Does anyone know of step-by-step instructions for getting fireplace.vim to evaluate ClojureScript code?


How’s the bundle size coming along? Also, I’m curious what back end most of you are using? Node with CLJS, Clojure with???, Elixir, etc?

I’m spinning up a small side project, and started it out with vanilla JS and Node. Bundle sizes are tiny, startup times are fast, lots of concurrent connections, etc... But I really don’t enjoy the ecosystem or language, so am probably going to port it over to Clojure. Clojure has spoiled me. :/


ClojureScript has a baseline which you cannot go under. Can’t remember the exact number but it’s something like 250k (advanced compilation but not gzipped).

For this you get the immutable data structures, and a decent chunk of the standard library, which you would use anyway.

On top of that, everything else that you get from the ClojureScript ecosystem, which is run through the Google Closure Compiler, is added incrementally. Use only one function, pay only for one (and its dependencies).



Well, sure, for hello world! But these days anything you do with CLJS will involve the data structures, which is what brings in the dependencies :)


Bundle sizes have never been an issue for me. You're not really supposed to use ClojureScript for trivial JavaScript. So for anything non-trivial, bundle size of ClojureScript and pure JavaScript start to even out.

Backend is Clojure off course , though ClojureScript on the backend is starting to shape up as well, in case you're already familiar with the Node standard library and ecosystem. It can be a good alternative.

If you intend to only have trivial JS mixer in with your HTML, then better to go for a pure Clojure server side rendering with a few embedded JS snippets. Similar to what you'd do if using Ruby on Rails or Django.




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

Search: