shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
2021-05-12T03:37:57.115500Z

Can I run build-report at the same time a dev build watch is running, or should I stop the dev build watch first?

thheller 2021-05-12T07:33:09.119700Z

the docs mention that, you can run them while watch is running

2021-05-12T07:51:58.129600Z

Indeed! Sorry I missed that. Thanks!

2021-05-12T03:58:36.116400Z

And another question: is it expected that the function names in stack traces are less helpful than they maybe could be?

thheller 2021-05-12T07:33:48.119900Z

dunno, I'm guessing they are all anonymous functions?

Robert Pofuk 2021-05-12T07:20:51.118300Z

Hi! I was trying to set

:module-loader    :no-inject
Based on code https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/build/targets/browser.clj should be ok:
;; true to inject the loader data (which changes the signature)
              ;; any other true-ish value still generates the module-loader.edn data files
              ;; but does not inject (ie. change the signature)
              (true? module-loader)
              (inject-loader-setup-release config)
But spec for module loader forces bolean (s/def ::module-loader boolean?) What is missing in my setup to avoid inclusion of module loader in js?

thheller 2021-05-12T07:32:10.119500Z

@robert.pofuk thats a boolean only, so just :module-loader false? what are you trying to achieve? that comment refers to old code that doesn't exist anymore

thheller 2021-05-12T07:33:09.119700Z

the docs mention that, you can run them while watch is running

thheller 2021-05-12T07:33:48.119900Z

dunno, I'm guessing they are all anonymous functions?

Robert Pofuk 2021-05-12T07:43:11.126200Z

I have multiple we applications, all of them are build with shadow-cljs, clojurescript, react material ui. I would like to share some code between them. Because I would like to avoid re-building all of them every time shared peace of code changes i wanted to modularize them. App 1:

MODULES:
:main {:entries [:react, :material-ui]}
:feature-1 {:entries [alpha/feature-1]}
App 2:
MODULES:
:main {:entries [:react, :material-ui]}
:feature-2 {:entries [alpha/feature-2]}
App 3:
MODULES:
:main {:entries [:react, :material-ui]}
:feature-3 {:entries [alpha/feature-3]}
Then I would be able to load javascript produced from :feature-1 and :feature-2 modules into APP3 . All of them are compiled using :simple optimization and are forcing for all shared deps to be in main module. My assumption here was that I will be able to override loadig of modules and put in :feature-1 and :feature-2 modules inside
var shadow$modules = {"uris":{"main":[],
                      "feature-1":["<https://app1.example.com/js/feature-1.js>"]},
                      "feature-2":["<https://app2.example.com/js/feature-2.js>"]},
                      "infos":{"main":null,"feature-3":["main"]}};

thheller 2021-05-12T07:47:34.126900Z

that is not possible, separate :advanced builds are not compatible with each other

Robert Pofuk 2021-05-12T07:47:52.127100Z

All of them are compiled using :simple optimization

thheller 2021-05-12T07:48:26.127300Z

even then that is questionable, :simple is also gigantic

2021-05-12T07:51:58.129600Z

Indeed! Sorry I missed that. Thanks!

thheller 2021-05-12T07:53:42.131200Z

you can set :module-loader-init false in your build config

thheller 2021-05-12T07:54:10.132200Z

and then initialize the loader via shadow.loader/init yourself. you can change the shadow$modules however you want before that

thheller 2021-05-12T07:54:56.132900Z

but I strongly advise against doing this. it will have unintended consequences.

Robert Pofuk 2021-05-12T07:55:35.133500Z

I know it is big 4x in my example. But sharing modules between apps would be amazing. I could have multiple teams in parallel developing without having 1 project as bottleneck. Also I could use this feature as feature toggle, rewrite module from scratch and so on... And javascript it self makes it easy to load code on demand and then it would be cool to utilize this in clojurescript. I only did small comparison and 2 different apps create same output of same code in module.

thheller 2021-05-12T07:58:46.134100Z

but if you care about performance at all then :simple is a dealbreaker

thheller 2021-05-12T07:59:26.134600Z

you can't possibly regain that loss from sharing code

thheller 2021-05-12T08:02:12.135800Z

the trouble is that even with :simple some code is rewritten in incompatible ways

thheller 2021-05-12T08:02:34.136300Z

if you just want to move out the JS dependencies and share those you can do so by using :js-provider :external

thheller 2021-05-12T08:02:49.136700Z

but sharing :modules will end up in trouble at some point

Robert Pofuk 2021-05-12T08:04:57.137900Z

Thank you for help! I will try to figure out if it is worth the risk and load the modules on my own or find a way how to compile things together.

Franklin 2021-05-12T09:12:22.138500Z

I have a macro that looks like this

(defmacro reg-event-assoc-in [name seq-of-kw]
  `(re-frame/reg-event-db
    ~name
    (fn [db# [_ value#]]
      (assoc-in db# ~seq-of-kw value#))))

Franklin 2021-05-12T09:12:44.138600Z

and I call it as follows:

Franklin 2021-05-12T09:13:01.138900Z

(utils-events/reg-event-assoc-in ::accounts-dropdown-selected-option
                                [:accounts-dropdown :the-selected-option])

Franklin 2021-05-12T09:13:49.139100Z

shadow-cljs keeps throwing this error:

4 | (utils-events/reg-event-assoc-in ::enable-new-project-modal?
-------^------------------------------------------------------------------------
Syntax error macroexpanding cljs.core/fn.
Call to cljs.core/fn did not conform to spec.
-- Spec failed --------------------

  ((clojure.core/apply
    clojure.core/vector
    (clojure.core/seq
     (clojure.core/concat
      (clojure.core/list 'quagga.utils.events/db__31345__auto__)
      (clojure.core/list
       (clojure.core/apply
        clojure.core/vector
        (clojure.core/seq
         (clojure.core/concat
          (clojure.core/list 'quagga.utils.events/_)
          (clojure.core/list
           'quagga.utils.events/value__31346__auto__)))))))) ...)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

should satisfy

  vector?

or value

  ((clojure.core/apply ... ...) ...)
    ^^^^^^^^^^^^^^^^^^

should satisfy

  vector?

-- Relevant specs -------

:shadow.cljs.devtools.cljs-specs/param-list:
  (clojure.spec.alpha/and
   clojure.core/vector?
   (clojure.spec.alpha/cat
    :params
    (clojure.spec.alpha/* :shadow.cljs.devtools.cljs-specs/binding-form)
    :var-params
    (clojure.spec.alpha/?
     (clojure.spec.alpha/cat
      :ampersand
      #{'&amp;}
      :var-form
      :shadow.cljs.devtools.cljs-specs/binding-form))))
:shadow.cljs.devtools.cljs-specs/params+body:
  (clojure.spec.alpha/cat
   :params
   :shadow.cljs.devtools.cljs-specs/param-list
   :body
   (clojure.spec.alpha/alt
    :prepost+body
    (clojure.spec.alpha/cat
     :prepost
     clojure.core/map?
     :body
     (clojure.spec.alpha/+ clojure.core/any?))
    :body
    (clojure.spec.alpha/* clojure.core/any?)))

Franklin 2021-05-12T09:13:57.139300Z

any pointers on how to fix this?

Franklin 2021-05-12T09:14:02.139500Z

can I silence the spec checks?

thheller 2021-05-12T09:46:47.139700Z

the _ is the problem, use ignored# or so instead

thheller 2021-05-12T09:47:09.139900Z

also this doesn't need to be a macro at all, just use a function

thheller 2021-05-12T09:48:14.140100Z

(defn reg-event-assoc-in [name seq-of-kw]
  (re-frame/reg-event-db name
    (fn [db [_ value]]
      (assoc-in db seq-of-kw value))))

thheller 2021-05-12T09:48:50.140300Z

you can't silence the spec checks since they are telling you that your code is incorrect and won't compile

Franklin 2021-05-12T10:19:18.140500Z

thank you

Aron 2021-05-12T11:48:29.145900Z

I have a beginner question this time. I suspect the answer might not be shadow-cljs related, but I am not sure yet. Basically, I have two different problems related to testing, and I would like to solve them both at once. I am using a :node-test target to compile puppeteer tests that I run manually. The problem is that sometimes I only want to run a single test, but the only way to easily configure this so far was through the :ns-regexp config. Is there a conventional solution to this problem? I can imagine writing an ad-hoc solution that takes CLI arguments and calls the tests or not based on that, but I am always wary of reinventing the wheel. And the second problem is that similarly through CLI arguments, I would like to feed different data to the same tests. Anyone here has some suggestions for some tooling, any kind of tooling, that would make both these problems easier to solve? Or should I just give in and code it up myself?

thheller 2021-05-12T11:50:23.146300Z

:node-test already takes CLI arguments

Aron 2021-05-12T11:50:42.146600Z

already I start to feel stupid

Aron 2021-05-12T11:50:47.147100Z

smh

thheller 2021-05-12T11:50:52.147300Z

try --help, or --test=a.single.ns or --test=a.single.ns/test-name

thheller 2021-05-12T11:51:34.147700Z

I think I didn't document those when I added them

Aron 2021-05-12T11:52:27.148100Z

you don't mean config-merge I am sure

thheller 2021-05-12T11:52:43.148500Z

no, when running the test node the-test-file.js --help

thheller 2021-05-12T11:52:58.148800Z

not a build option at all, just a runtime thing

Aron 2021-05-12T11:53:21.149400Z

trying

thheller 2021-05-12T11:53:22.149500Z

the second part with passing custom data is not supported since tests themselves don't take arguments

Aron 2021-05-12T11:54:17.150400Z

if I can do any cli based logic, then i can load the necessary data from disk

Aron 2021-05-12T11:54:53.150900Z

compile the tests with different fixtures/mock data

thheller 2021-05-12T11:55:09.151100Z

what you do in your tests is up to you

Aron 2021-05-12T11:55:54.151400Z

I wish, but my colleagues have a say too : )

thheller 2021-05-12T11:57:38.152Z

TEST_DATA=foo.txt node the-test-file.js --test=that.one/test-thing

thheller 2021-05-12T11:58:03.152600Z

and in your test (fs/readFileSync js/process.env.TEST_DATA) or whatever

Aron 2021-05-12T11:58:38.152800Z

thank you, immensely helpful as ever