Fork me on GitHub

@mynomoto Here you go:, check the "Better interop with native React"


Hey, could somebody point me example with shadow-cljs on frontend and clojure as a server? Is this worth doing or just use classic figwheel approach?


Nwm, figured out. Was easier than expected


Any success stories in using shadow-cljs to write node servers? Piggy-backing onto popular “mainstream” JS libraries (e.g. Express et al) while keeping the business logic in CLJS.


I think it is very common for most people to use Clojure on the server side (I do personally) so CLJS on the server is not too common yet.


Apparently so… unfortunately having a REPL-driven with Node is a bit frustrating. I managed to get a working nREPL CLJS connection from Atom to shadow-cljs, but it’s still a bit flaky.


The reloading story is much better though, and for people coming over from JS it should be a familiar experience.


I don't do much node development so if there are things that could be improved from the CLJS side let me know


One immediately obvious thing is that compilation failures didn’t show up in Atom. Given the multitude of moving parts, I’d like to do some triaging before creating bug reports, it could be my fault, or proto-repl, or some other thing…


what you can do is run shadow-cljs from a terminal inside atom


terminal-plus or something like that


I don't know it proto-repl shows any stdout output from the REPL.


I am trying out shadow-cljs 2.1.4 we are coming from 2.0.x and we get babel errors for some reason.. Was there a change that triggers this?


ReferenceError: [BABEL] shadow$empty.js: Unknown option: /home/mitchel/Development/atlas-crm-next/node_modules/react/react.js.Children. Check out  for more information about options.

A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:

  `{ presets: [{option: value}] }`
  `{ presets: [['presetName', {option: value}]] }`


Oh I had a .babelrc that was causing this.. Sorry for the noise


.babelrc should be ignored for files in node_modules so if that wasn't an issue before thats definitely a bug


That might be a bug then.. Btw really loving the new loading indicator


And the warnings look a lot better too


k, I'll check it out


But it also said I had a configuration error so it might be my fault


yeah but it shouldn't even be looking at .babelrc so it shouldn't matter whats in there


hello, I'm getting a weird warning from shadow-cljs:


------ WARNING #1 --------------------------------------------------------------
 File: /Users/wilkerlucio/Development/pathom/src/com/wsscode/pathom/core.cljc:70:1
  67 |                     (gen/call-gen g rdn size))
  68 |                   (gen/call-gen (gen/return []) rdn size)))))))
  69 |
  70 | (s/def ::mutation-expr
 No such namespace: operation.on, could not locate operation/on.cljs, operation/on.cljc, or JavaScript source providing "operation.on"
  71 |   (s/with-gen
  72 |     (s/and list? (s/cat :mutate-key symbol? :params (s/? ::params)))
  73 |     #(gen/let [key (s/gen '#{do-something create/this-thing operation.on/space})
  74 |               val  (s/gen ::params)]


operation.on? my doesn't mention that at all


started happening after loading test.check and generator things


most likely the :require-macros thing again .. this is really beginning to bother me.


is this just test.check or do you have any macros involved in this?


just test.check and spec, these are my requires:


(ns com.wsscode.pathom.core
  (:refer-clojure :exclude [ident?])
    [clojure.spec.alpha :as s]
    [clojure.set :as set]
    [clojure.test.check :as tc]
    [clojure.test.check.generators :as gen]
    [ :as prop]
    [clojure.walk :as walk]
    [fulcro.client.primitives :as fp]
    #?(:cljs [goog.object :as gobj]))
     (:import (clojure.lang IAtom IDeref))))


seems like a bunch of stuff is relying in this broken behaviour 😞


at this point I feel like giving up and just adding the broken stuff


I tried to add :include-macros on all of then, but no effect


no the test.check stuff doesn't do it correctly (internally)


nothing you can do really


I have to finish some work stuff. I'll look into this after


thanks, what is been done wrong? does test.check has to require itself? just trying to understand


see the CLJS issue, it is missing the :require-macros for itself in .cljc files with macros


might also be spec itself


so the gen/let macro is not handled properly internally I assume


back to work


@wilkerlucio I just noticed that (s/gen '#{do-something create/this-thing operation.on/space}) is in your code?


is spec maybe trying to resolve that?


@wilkerlucio [clojure.test.check.generators :as gen :include-macros true] this seems to work?


but I'm not getting a compile error without it, only an error at runtime?


do you have the full code available so I can test this in your setup?


@thheller sorry the delay, was in meetings


actually my code has that, but it's quoted (sorry bad info before, didn't even occurred to me to look at quoted things)


it shouldn't try to eval it


(s/def ::mutation-expr
    (s/and list? (s/cat :mutate-key symbol? :params (s/? ::params)))
    #(gen/let [key (s/gen '#{do-something create/this-thing operation.on/space})
              val  (s/gen ::params)]
       (list key val))))


I can send the full source in a min


(do ;; s/def ::mutation-expr
    (s/and list? (s/cat :mutate-key symbol? :params (s/? ::params)))
    #(gen/let [key (s/gen '#{do-something create/this-thing operation.on/space})
               val  (s/gen ::params)]
       (list key val))))


this compiles fine


I'm going to try a few things, just at work now, limited time, probably going to do more later once I get home


(def sample-mutations '#{do-something create/this-thing operation.on/space})

(s/def ::mutation-expr
    (s/and list? (s/cat :mutate-key symbol? :params (s/? ::params)))
    #(gen/let [key (s/gen sample-mutations)
              val  (s/gen ::params)]
       (list key val))))


but that' weird, why I can't use the quoted directly there? I can try on pure cljs to see if it's a problem with cljs ou shadow, not sure at this point


on clojure side this is not an issue


clj build.clj
WARNING: No such namespace: operation.on, could not locate operation/on.cljs, operation/on.cljc, or JavaScript source providing "operation.on" at line 9 src/test/foo.cljs
WARNING: No such namespace: create, could not locate create.cljs, create.cljc, or JavaScript source providing "create" at line 9 src/test/foo.cljs


default cljs fails as well


thanks for helping with this debug


I'm looking if there is an issue on Jira, seems not, I'll open one


I'm trying to get back into blogging. I'll try to capture most of features of shadow-cljs and why they exist in future posts.


you know @thheller when i read through all the work you’ve done on this project, I sometimes wonder if it wouldn’t have been easier if the cljs compiler just did DCE analysis itself on the clojurescript side, then produced normal javascript code that was bundled by webpack, skipping the entire google closure compiler step.


I don’t think when CLJS started out that it was feasible to do that — closure was probably the right decision back then.


and the Closure Compiler compilation is still one of the best available, also we leverage the goog apis, when CLJS was build this was all state of art


Arguably it still might be.


yeah, but I guess the thing was to pick something robust, and the closure toolset is a good candidate, after all this is what google was using to build their major apps like gmail


oh yea i’m sure it was the right choice then. i am really just curious whether symbol renaming is worth it.


i’m just being selfish in terms of what I want: I think my life would be easier if the cljs portion of my code just built itself into a self-contained js package and interacted with npm modules just like other js code and let me do the packaging with webpack.


@thheller any interest in a PR for a CLI command that will auto generate a deps.cljs file from the package.json dependencies?


@lee.justin.m isn’t it possible to do this today? It is my impression that with shadow you can create an “npm module” that exports something and then you can consume it as you like.


The problem with shared code, you mention in the article is exactly my problem. I have an app that have two client SPAs, one node rest server and couple of small node services. With shadow-cljs I am actually starting to see the light on the end of the tunnel. Only thing that bother me now is the #dailyprogrammer compatibility for the front end SPAs development. My workflow is very dependent on its functionality.


@orestis that doesn’t solve the symbol renaming problem or the fact that you have to do so much work to call javascript from cljs. anyway sorry, it’s way off topic. i didn’t mean to clutter the channel.


Things that are exported should be not be renamed, I’m fairly certain that both shadow and the CLJS compiler can do that. Calling cljs from JS should not be that problematic given that CLJS functions are JS functions. You may have to write a JS shim layer on top though.


Yea I get all that. It’s just super error prone and clumsy as hell. That’s why people write libraries like cljs-oops just to avoid using externs. The npm integration is also clumsy, which is in part why we have shadow-cljs. If you are a medium level programmer like me who doesn’t fully understand (1) the internals of the google closure compiler, (2) the internals of cljs, (3) the intricacies of npm modules resolution and management, then it is a total nightmare to port an existing javascript website over. I don’t really know the answers, but I will say that it seems to me a lot of this chaos stems from (1) the fact that clojurescript takes over dependency management instead of integrating into the js ecosystem way of doing dependency management (2) symbol renaming


just as an example: these are the notes I took for myself as I worked through all this stuff


you can mark a symbol as external, so it doesn't get minified eg (def ^:extern some-thing)


I don't remember for sure if that is the correct keyword, but I'm pretty it exists


i realize there exist solutions. my point is that they clumsy and error prone and the documentation and tooling around this stuff is crazy complicated. my original point is that if we didn’t do symbol renaming, we could just call javascript and vs versa without any worries.


@lee.justin.m your notes are impressive and I feel your pain. shadow-cljs does things differently precisely because of the things you describe


CLJS itself is pretty broken and clumsy indeed


externs are still a challenging subject but variable renaming is one of the most important things when it comes to saving bytes. so we can't really get away from that.


especially with the huge names CLJS generates for its fns.


externs inference is actually pretty reliable today and will spot most of the issues. I have completely removed all externs from my builds and completely rely on the inference.


but again ... in CLJS it is still very unreliable


@thheller well i just did a git checkout -b shadow so i’ll let you know in a few hours how it goes 😛


the nightmare now is figuring out what this infernal leiningen template is doing for me to so i can use shadow instead


if it is anything but npm install react-dnd and (:require ["react-dnd" :as dnd]) let me know 😉


although IIRC react-dnd did some fancy stuff with HoC components and ES7 decorators


well i just mean i have this giant lein thing that some tool created for me that has a ring handler and figwheel and piggieback and all this stuff i don’t fully understand


i’m hoping i can just start a shadow watcher and things will work


@lee.justin.m :npm-module does what you asked. processes CLJS with closure but lets you do the final packaging with webpack or others. I still consider the Closure Compiler to be the most advanced JavaScript tool out there so there are no other options for me.


@colindresj I'd prefer if that was just a normal clojure function so ALL tools could potentially benefit from it. you can run shadow-cljs clj-run your.tool/build-deps-cljs ... to execute it. similary lein run -m your.tool/build-deps-cljs ...


@thheller that’s what I’m doing on my own, but was wondering if it would be worthwhile to have it available for others when they use shadow-cljs


I'm strill trying to figure out how I want to approach publishing libraries with shadow-cljs. I really wish there was a tool agnostic way of doing this. your fn would fit well into such a tool


not so much into shadow-cljs itself at this point since you can't use it to publish libs yet 😛


Haha right, that makes sense


Might put my function up on clojars or something and mention it here in case anyone else is doing libs with shadow-cljs


happy to include it in the readme/docs. still need to write that chapter on publishing libs


dumb question: what URL am I supposed to load once I have my watcher going? I tried to load but I get a shawdow-cljs generated webpage that has a link to Release Snapshots instead of my index.html


@lee.justin.m you need to configure a separate webserver for your build. see


9630 is the server for shadow-cljs itself which will eventually serve the GUI


okay i see. i think that’s working (although :http-handler {:http-handler shadow.http.push-state/handle}) gave me this error ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.Named. now my program is broken in some other way but it does appear to be loading.


is main! a convention for the entry point? i just followed your medium article and changed my code to use that symbol. in the lein template i had been using, it needed an init! symbol


do you need push-state? it is optional and should just be :http-handler shadow.http.push-state/handle not nested in itself 😛


the medium article was written by @jiyinyiyong. no it is not convention. I always recommend the init/start/stop setup in my template.


ie. call init from HTML, which calls start. live reload calls stop :before-load, then start :after-load


the push-state issue was my fault doh!


spiffy. that’s working and, unlike 80% of the time with cljs, I actually understand why 🙂


by the way, i meant to say that the tweaked http section is very nice.


I also tweaked the config specs so the error you run into with :http-handler gets a reasonable error. keep the feedback coming if you run into anything. it helps a lot.


one small thing: for some reason, shadow is loading the minified development version of react. I tried to add

:js-options {:resolve {"react" {:target :npm
                                                   :require "react/dist/react.js"}}}}}}}
but it doesn’t seem to change anytning