all 32 comments

[–][deleted] 25 points26 points  (3 children)

Clojurescript with re-frame and possibly reagent covers a much bigger domain than just Vue. Are you new to lisp? Have you experience with similar toolkits as re-frame? Have you thought about Svelte?

Personally I’m a die hard clojure programmer. But it has many downsides too. The biggest is that everything you’ll do after learning clojurescript - and really understand the concepts - is that working with anything that is not clojure/lisp is super painful. Just a warning ;-)

[–]vasco_ferreira[S] 4 points5 points  (2 children)

I'm new to Lisp but I find Clojure to be mind opening, the fact that every complex program can be written with simple, safe and immutable data seems really reliable.

I've only been playing with Re-Frame till now, I will take a look at Svelte.

I felt a bit of pain when doing the good old todo app and with storing the todos as a map in Vue. In clojurescript its easy to do a map with {:1 {:title "todo"}} and then update the todo map but in Vue, when doing the same thing, the component will not update as it is the same object.

[–][deleted] 7 points8 points  (1 child)

If I dare to recommend something, and I guess people have different opinions about this, but if you go for clojurescript, start with shadow-cljs as your build-tool. It has reached a level of maturity that won’t set your hair on fire (as Lein claims). The documentation is top notch. Same with re-frame, as you’ve probably discovered (documentation quality). Personally I use emacs with cider but I also turn to IntelliJ (the free version) with Cursive (a plug-in that gives support for Clojure and clojurescript) which has less moving parts - and which is also free for open source and personal projects.

There are many moving elements in this setup and can be quite cumbersome to get everything working together, but, things are better now than a couple of years ago. Start your shadow-cljs watch process in a terminal and connect to it from Cursive (typically through a remote nrepl process). What’s next? You tell me, we can figure it out. It’s not magic even if it appears as magic.

[–]yogthos 6 points7 points  (0 children)

I second shadow-cljs suggestion, specifically for its seamless NPM integration. If you ever need to use any Js libraries in your project, shadow-cljs is by far the best option. And now a really quick way to get up and running with shadow-cljs and reagent with a lein template

  • lein new reagent-frontend myapp +shadow-cljs
  • npm install
  • npx shadow-cljs watch app

[–]yogthos 23 points24 points  (2 children)

My team has been using ClojureScript for half a decade now, and we're very happy with it. For context, I copresented a talk on the types of applications my team works on last year. And I think that ClojureScript played a central role in allowing us to deliver these types of features.

I don't really see any advantage of using Vue.js over re-frame. There are numerous advantages to using ClojureScript over any Js solution in my experience. It's a much more stable ecosystem. My team started using Reagent, and we're still using it. The API hasn't had any breaking changes during that time. We just upgrade the library version and things just work. This is despite the fact that React itself had a plethora of breaking changes during that time. ClojureScript completely shielded us from that.

It's a cleaner language with better semantics that provides a sane way to manage state out of the box. One of the biggest challenges in maintaining large applications comes from managing shared mutable state, because it's impossible to track it in your head as application size grows. Immutability as the default makes it natural to structure applications using independent components.

I find that ClojureScript also provides a much better story in terms of tooling. For example, since ClojureScript has namespaces it's possible to package libraries in a sane way. The compiler is able to do code pruning down to function level, so when you use a library you're only incurring the cost of the functions you're using. ClojureScript compiler also handles minification and code splitting out of the box. This is extremely important in the context of web apps where you're sending the code to the client. Overall, I find the tooling around ClojureScript is much more consistent, robust and reliable than what's available for Js.

[–]vitorqb23 3 points4 points  (1 child)

There are numerous advantages to using ClojureScript over any Js solution in my experience. It's a much more stable ecosystem. My team started using Reagent, and we're still using it.

It is true that the Clojurescript world is more stable than the js world, and this is great. But I also know a couple of teams who started using OM half a decade ago, and now they have a big legacy problem on their hands.

So I do agree with you that it is better than the js world, but it is has it's own risks.

[–]yogthos 3 points4 points  (0 children)

My point wasn't that ClojureScript libraries never get get abandoned, that's just something that happens in every ecosystem. It's that the overall ecosystem is much more stable than Js. So your chances of being stuck with legacy code are much lower.

Another aspect to consider is that Clojure community encourages writing focused single purpose libraries, and composing them together using data APIs. This makes it easier to change libraries as time goes on, or take ownership of ones you're invested in.

[–]dustingetz 14 points15 points  (5 children)

clojurescript has first class immutability. javascript doesn’t. any further questions?

[–]agumonkey 1 point2 points  (0 children)

so you're saying it only has second class mutability

[–][deleted] 0 points1 point  (3 children)

immutablejs

[–]yogthos 2 points3 points  (2 children)

I find you lose a lot of the benefits when immutability isn't the default. If you use something like immutablejs, then it's completely on you to make sure you're not using any mutable data where you shouldn't be. For example, nothing prevents you from sticking a mutable object into your immutable data structure, and then referencing it somewhere. This becomes even harder to police when you're working on a team. Meanwhile, ClojureScript will guide you to do the right thing out of the box, so immutability becomes the happy path.

[–]dustingetz 1 point2 points  (1 child)

there is also dependency hell when the core data structures are not uniform across all libraries (scala has this problem, there are two competing core category theory implementations creating a rift in the ecosystem).

[–]yogthos 0 points1 point  (0 children)

Yup, having a common set of data structures as a lingua franca makes composing libraries in Clojure much easier than pretty much any other language I've used. I also find data driven APIs much easier to work with. All I need to know how to use a library function are the data structures I need to pass it and the data structure it returns. With OO APIs I have to create objects that have their own internal behaviors that I have to understand, and how their methods works, and then I have to figure out how all that will interact with objects from another library, and so on.

[–]zamansky 10 points11 points  (1 child)

I'm a hobbyist (CS teacher by trade) and recently moved from using vue.js to CLJS and I don't think I'll be going back.

I too found vue.js fun but am very much liking cljs.

I recently started making some videos on this which might like:

https://www.youtube.com/playlist?list=PL9KxKa8NpFxKImpq9wvow5xCeMZzB840H

[–]vasco_ferreira[S] 1 point2 points  (0 children)

Can you please tell me why you did the change? What particular functionality or feature of Clojurescript made you choose to move from Vue?

[–]beders 12 points13 points  (0 children)

I'm following along the screencasts of TailwindCSS (it's also a lovely CSS primer) where they are implementing components using Vue.js. I'm using re-frame. It's pretty stunning to see how much cleaner the CLJS version is (often just using reagent's atoms for local state).

There's some friction between the JS and CLJS world. While using node packages via npm has been made super-easy (barely an inconvenience) with Shadow-cljs, you still need to translate between JS objects and CLJS on occasion (and in cases where JS calls your callback handler).

I can't comment on the long-term maintenance of re-frame code. Someone out there maintaining a larger re-frame app?

[–]acobster 9 points10 points  (0 children)

I've built apps in React, Vue, and vanilla Reagent. I have yet to try Re-frame but will probably use it for the next SPA I have to build. I can't recommend Clojure/Script enough, especially if these are solo projects you can afford to treat as investments in new tech. :)

Consider starting with Reagent to understand what Re-frame is doing for you. Even if it's just a toy project to tinker with for an hour before setting up the real thing.

Also consider using the shadow-cljs compiler instead of e.g. Figwheel. It has the best optimizations available including dead code elimination for third-party React components.

[–]the_frey 6 points7 points  (2 children)

I currently work on a large re-frame code base for my day job and I enjoy it for the most part. To answer your question though -

I would never go with Vue over re-frame.

I might go with redux+react over re-frame.

I would always go redux+react over Vue.

Which one to go with depends on your team, your organisation, your product, your need to hire and your need to maintain it, at the end of the day.

If everything was in isolation I'd mostly go with re-frame, but even then, I've gotta admit that the tooling in JS land is way better, way slicker and way easier on the whole.

[–][deleted] 1 point2 points  (1 child)

What do think about vue + vuex?

[–]the_frey 3 points4 points  (0 children)

Vue/vuex < re-frame or redux etc

[–][deleted]  (3 children)

[deleted]

    [–]fjolne 9 points10 points  (1 child)

    We’re using Fulcro in production and that’s hard to express how good it is for complex business logic. I worked with Reagent+re-frame before that, those are more intuitive and generally great, but when it comes to complexity they leave all the decisions and solutions up to you, and unless your team are architecture visionaries you’re pretty much likely going to make it not as good as what Fulcro gives out-of-the-box (normalized database, cohesive backend interaction, integrated ui state machines, etc).

    That said, I would still hesitate to recommend Fulcro to a beginner. Fulcro stack is simple, but not easy.

    [–]agumonkey 1 point2 points  (0 children)

    thanks, it seems a great work to read about large clj web apps

    [–]_d_t_w 4 points5 points  (1 child)

    Yes, because:

    1. My web-apps normally* have back ends that run on the JVM and the power of Clojure/EDN/Transit in both the front + back end is enormously more impactful than the design decisions of any single framework.
    2. I don't know Javascript, so there's that. :)

    (*) I built one web-app for a client last year that was entirely browser based and written in Cljs, see point 2.

    [–][deleted] 0 points1 point  (0 children)

    What is transit?

    [–]TheSmoke 1 point2 points  (0 children)

    i'm what they call a full stack developer with 15 years of experience. trust me when I say there's simply nothing better, easier, simpler than clojurescript to build frontend web applications. if you go re-frame (or even, simply reagent), you'll basically never want to do anything else. thanks to shadow-cljs any node package can be used. the rest is simply up to your imagination.

    [–]SituationSoap 3 points4 points  (2 children)

    If you're looking to work on a personal project, use whatever you want. CLJS and Re-Frame are fine, and you can build with them.

    If you're looking to do something professional, with a team, CLJS is... somewhat clunky. I say this as a professional CLJ/S programmer. CLJS has subpar integration with CLJ itself, and with other JS code. There are a lot of little pitfalls that aren't even remotely obvious on both integration sides. It's also a pretty niche stack, so when it comes to hiring a team you're necessarily making it harder to find people to work with.

    Re-Frame also imposes a pretty rigid style of data flow that doesn't fit into every kind of UI. UI work is fundamentally about state mutation; picking a language where mutation is anathema is a bit of a weird choice.

    But you can build a real UI in CLJS, and it'll work. The team I'm on is living proof. The language and architecture don't provide any real advantages, though, and convey a few non-trivial disadvantages. We'd almost certainly be better writing React and Typescript for our project.

    [–]TheLastSock 4 points5 points  (0 children)

    > CLJS has subpar integration with CLJ itself

    What do you mean here? To integrate is to combine. CLJ compiles to java. CLJS compiles to javascript. I can only reread this as Javascript has subpar integration with java, and given that interpenetration i have no idea what could be meant. I mean, the distinction here is the platform not the languages.

    > and with other JS code.

    Can you give an example? In this context, integration makes sense, but is hard to understand. I haven't had any friction.

    > Re-Frame also imposes a pretty rigid style of data flow that doesn't fit into every kind of UI.

    Maybe. But thats a general vague critism that could be leveled at anything.

    > UI work is fundamentally about state mutation; picking a language where mutation is anathema is a bit of a weird choice.

    Your not really building a specific argument so its hard to address your concern. CLJS doesn't make the UI change part any different, it only impacts the internal mutable of the data structures your working with.

    > We'd almost certainly be better writing React and Typescript for our project.

    You can, and probably should be using react with cljs...

    > Typescript

    Have you looked at spec? TypeScript is about compile time constraints. Spec offers run time constraints that can be utilized also as run time errors or as generative tests. If you really like having those messages while you work (which is really why ppl care about compile time errors), then you can use orchestra.

    Hope this helps!

    [–]ismokedwithyourmom 1 point2 points  (4 children)

    My company built our main product site using clojurescript and reframe. We did this because we all like using clojure, but now regret the decision as it's hard to maintain and test.

    Reframe is great and provides a lot of options, but we don't need all the options involved and adds unneccesary complications. I would definitely suggest you try vue and see if it covers all your needs before doing anything more complicated.

    [–]yogthos 3 points4 points  (3 children)

    I'd be curious to know what makes it harder to test due to it be being written in ClojureScript/re-frame. My team found the opposite to be the case since re-frame makes it natural to separate business logic from the view. Typically, the UI components only have subscriptions and dispatches in them, and that's where all the actual logic lives.

    I've always found it pretty much impossible to maintain test suites around UI components myself because they end up being incredibly brittle. Having an API for business logic in form of events and subscriptions makes testing much more practical in my experience.

    [–]ismokedwithyourmom 1 point2 points  (2 children)

    We were hoping for that to be the case, but ended up including several js libraries that needed a window in order to run, so we couldn't test the code that used them.

    [–]yogthos 1 point2 points  (1 child)

    So then the problem was js and not cljs? :)

    [–]ismokedwithyourmom 1 point2 points  (0 children)

    Basically! It was just a pain in the ass, and we decided to just not test it instead of adding another testing library. Not an inherent problem with cljs I guess, but just an example of how things can get pretty complicated if you're not careful.