Time to drop Om?

I’m considering dropping Om from Chestnut. The main benefit of Chesnut is taking care of tedious setup so you don’t have to. Adding Om is very straightforward, more so than it used to be, you just add it to the project, there aren’t many caveats.

Even if we don’t drop Om, we’ll have to decide to stick with “classic” Om, or switch to om.next. But om.next is pretty much a new react wrapper, so in that case we could just as well switch to Reagent, or Rum, or … and if we’re going down that path we should probably switch to the most popular option, which looking at clojars downloads is Reagent.

So… drop Om and don’t put in a react wrapper by default? or switch to Reagent and use that?

Actually looking at the graph again, it’s hard to say if reagent is really the biggest now, since Om is spread over two orgs (om and org.omcljs), so you really have to add the blue and red curver together. Also ignore the data point for January, obviously there’s not enough download data yet for this month to say anything useful.

Can you put a lein template switch to allow a choice?

Obviously more work but I think those numbers could be skewed by templates (such as chestnut) that default to one or the other. I know I’ve generated and built several projects that defaulted to reagent which I later manually converted to Om next (or other.)

I’ve thought about that as well. The problem is that each switch multiplies the effort is needed to test a release. This is one of the reasons Chestnut has seen so few releases last year. I don’t want to put a release out until it’s 100% solid, which means manual testing all switches and combinations thereof. If anything I’d prefer to drop switches in this release. I already got rid of --cljx because that’s deprecated now. --speclj will go away since I want to incorporate doo for testing.

Right now we already have a swtich for --om-tools, but not e.g. for sablono, which I think nowadays would make more sense.

If we go the route of switches we need to choose which of these we support

  • om + om.dom
  • om + om-tools
  • om + sablono
  • om.next + …
  • reagent
  • quiescent
  • rum

It’s all quite arbitrary, without a clear winner. Still I’m not sure how to proceed. Options I’m willing to consider

  • drop them all, document how to add the most popular options
  • only support om.next + sablono
  • only support reagent
  • support om.next with sablono + reagent as a switch

I’m of two minds on this question. On one hand, it seems the point of a Leiningen template is to be opinionated, so pick one (or two) and go with that. On the other hand, it would be neat if Chestnut could have the ability to add components after-the-fact (something like Padrino), but I don’t think Lein is really set up for that (or at the very least Chestnut would maybe need to become a template and a Lein plugin).

Funny that you mention that, that’s exactly what I’ve been thinking of, have a base template, and then be able to add things to it afterwards. So we would have Chestnut, the leiningen template, and Chestnut the leiningen plugin

lein new chestnut my-project
cd my-project
lein chestnut add reagent

I already experimented a bit with this approach a year ago based on rewrite-clj, my doodling can be found here: https://github.com/plexus/seed

rewrite-clj is great, but it’s rather low level, so the idea with seed is to add semantic operations like

(add-project-dependency '[foo.bar "1.0.1"])
(append-to-method-body 'my-project.core/main '(foo 123))

It has irked me from the beginning that we have this (mostly) homoiconic language, but have to resort to text-based templating to generate code.

I’ll toy with this a bit more the coming weeks. This would offer a whole new perspective since

  • we can delegate feature flags to these “recipes”
  • there’s no added complexity to the base template, these “recipes” are completely orthogonal to the main template
  • it’s possible to provide transformations that work against existing projects. This will not always work, but it’s still pretty cool and often requested.
  • in case a recipe no longer cleanly applies, you can pretty much read it like a tutorial and apply the changes yourself.
1 Like

One tricky part with this is getting the formatting (whitespace) right. Although we could just bail out and run all code through cljfmt when we’re done :slight_smile:

Just my 2cents, I like this option the most, and it would seem to be in line with figwheel’s own --om/–reagent switches.

Documentation for more combinations would also be most helpful.

I got started with web deving on clojure on chestnut because of the ease of use of configuration over picking my own. Having an opinionated default template definitely helps new users being able to lein new, and getting something up and running over having to read the docs and diffs between 5 combinations of libraries before even getting something run.

I can see the point of being opinionated and “batteries included”. I think I’ll go with om.next+sablono then as opinionated default, this makes the most sense since Chestnut is known as an Om template to begin with. I’ll drop the --om-tools flag, but probably add a --reagent flag later on based on rewrite-clj. I’m leaving it as a next step because doing it with syntactic transformations will take laying some groundwork.

The good thing about this would be that other flags like --less and --sass can be implemented in the same way, thus ensuring that we never generated malformed code. (it might be wrong code, but it least it would always parse).

1 Like

Allow me to reverse what I’ve said previously now that I dug in some - I know that we conferred a while ago, but with .9 is out in the wild, still on om by default, with no changes to the underlying libarry, there still might be some time to discuss this.

I’ve been getting super heavy into reagent as of late. As a newbie-friendly template, I find it is significantly easier to get started with reagent. I’d be more than happy with Chestnut having switch the default.

Thanks for the reminder. I’ve added --reagent and --vanilla flags. These will change the project dependencies, and cause a different core.cljs version to be rendered.

Reagent:

(ns {{project-ns}}.core
  (:require [reagent.core :as reagent :refer [atom]]))

(enable-console-print!)

(defonce app-state (atom {:text "Hello Chestnut!"}))

(defn greeting []
  [:h1 (:text @app-state)])

(reagent/render [greeting] (js/document.getElementById "app"))

Vanilla

(ns {{project-ns}}.core)

(enable-console-print!)

(set! (.-innerHTML (js/document.getElementById "app"))
      "<h1>Hello Chestnut!</h1>")

I’ve released it as 0.10.0-SNAPSHOT, so you can give it a go with

lein new chestnut my-app --snapshot -- --reagent

Make sure to use the -- separator, I couldn’t get it to work without it. Leiningen options go before --, template options after. I did just upgrade to Leiningen 2.6.1, maybe the behavior changed, I remember it passing through any unrecognized options to the template.

1 Like