Fork me on GitHub
#shadow-cljs
<
2019-06-17
>
caleb.macdonaldblack00:06:48

Can I shadow-cljs watch two builds in the same page at the same time? When I try to do this shadow-cljs watch app logger one of them cannot load properly because of 404s on the scripts it loads

aisamu01:06:47

Does it also happen when you shadow-cljs watch app, load shadow-cljs' UI and click the logger build?

aisamu02:06:38

Hmmm. Watching works here with multiple builds (3+), so it's definitely possible! Are they perhaps sharing the output-dir? Does the second build work flawlessly when started alone?

caleb.macdonaldblack02:06:44

Yeah, they work fine alone

caleb.macdonaldblack02:06:51

Also they share the output-dir

aisamu05:06:55

I suspect the issue is sharing the output-dir

danielneal07:06:16

react does give us react native, so for now I'm locked in to it...

pyr08:06:01

Hi, Since shadow-cljs and cljsjs don't play well with each other, are there documented ways of making things like soda-ash work well?

pyr08:06:04

looking at it, the adapt-react-class can be called on semantic-ui-react directly I suppose

thheller09:06:14

@caleb.macdonaldblack you cannot load 2 dev builds on the same page in the browser

👍 4
p-himik09:06:51

What would be the preferred way of writing a macro that is supposed to expand to CLJS code that uses Shadow-CLJS-style requires? E.g. I have

(:require ["@material-ui/core" :as core]
          [reagent.core :as reagent])
in my CLJS ns declaration. I then write some boilerplate code for each MUI component that I'd like to shove in a macro. I think I can get away with just assuming that reagent and core aliases are available when the expanded CLJS code is compiled. But is there a better alternative?

thheller09:06:53

option a) is creating "wrapper" functions in the macro ns. (defn foo [...] (core/foo ...))

thheller09:06:09

option b) pass whatever material thing you are wrapping into the macro (the-macro core/thing ...)

thheller09:06:59

you can in theory get the alias from the compiler env too but thats a bit shadow-cljs specific

thheller09:06:34

also don't ever require "@material-ui/core" directly, be more specific with the requires

thheller09:06:47

otherwise you are adding a lot of maybe unused code

p-himik09:06:42

Not sure I understand (a). Where would that core come from? "@material-ui/core" is not available for CLJ. Or did you mean basically what I said, so that function would end up being called only in the expanded code? What about a macro that does something like \(do (require ["@material-ui/core" :refer [Toolbar]]) (... using Toolbar))`? Yes, sure - I oversimplified the ns declaration a bit. I require only the things that I need.

thheller09:06:08

thats option b I mentioned?

thheller09:06:40

would help to know what the macro actually is supposed to do

thheller09:06:56

why do you need to wrap MUI?

p-himik09:06:29

No-no. Option (b) I don't even consider as long as there are other alternatives - it still leaves quite a bit of boilerplate. OK, give me some time to actually come up with something. My macro-fu is not what it's supposed to be.

mhuebert10:06:30

i’m not sure it’s currently possible to avoid boilerplate with material-ui. AFAIK we need to have each specific component we want as an individual :require inside of ns, and we can’t manipulate ns forms with macros

mhuebert10:06:31

material-ui recently added support for tree-shaking but I don’t think it works with cljs

thheller10:06:09

yeah that currently doesn't work. I have some ideas on how to make it work but it is a lot of work I currently don't have time for

mhuebert10:06:36

yeah i saw some of your discussions about that somewhere. this stuff seems difficult and a moving target

thheller10:06:13

yeah its a cutting-edge feature in webpack so doesn't seem "final" yet

thheller10:06:40

not many packages support it either yet so we'll see

p-himik10:06:22

Ideally, it would be something like this:

(defmacro defcomponent [cljs-name args]
  ;; Intended usage:
  ;; (defcomponent app-bar [{:keys [classes color position] :as props} & children])
  ;; (defcomponent toolbar [{:keys [classes component disable-gutters variant] :as props} & children])
  ;; The full props specification is needed for correct parameters info during development.
  ;; E.g.in Cursive, `defcomponent` could be resolved as a function, making Cursive show that
  ;; `app-bar` accepts [{:keys [classes color position] :as props} & children] as parameters.
  (let [;; "app-bar" -> "AppBar"
        comp-name (string/join (map
                                 string/capitalize
                                 (string/split (name cljs-name) #"-")))]
    `(do
       (require ["@material-ui/core" :refer [~comp-name]])
       (let [comp (reagent.core/adapt-react-class ~comp-name)]
         (defn ~cljs-name [& props+children]
           (into [comp] props+children))))))

p-himik10:06:54

There should also probably be (require [reagent.core]) but you get the idea.

mhuebert10:06:13

isn’t require only a REPL thing in cljs?

thheller10:06:15

yeah thats not possible

thheller10:06:26

:refer is kind of a trap here since it doesn't do what you think it does

thheller10:06:45

webpack style tree shaking is not support for JS packages as mentioned above

thheller10:06:11

you actually need different requires to make that work

thheller10:06:25

(:require ["@material-ui/core/Button" ...])

thheller10:06:21

but generating requires dynamically is not possible in any way

p-himik10:06:37

You're giving me too much credit. 😄 I don't have any idea what any of this is supposed to be doing. And I've never been a proper JS developer. Hmm, but (:require ["stuff/core" :refer [Component]]) seems to work just fine, just as (:require ["stuff/core/Component" :default Component]).

thheller10:06:55

if does work just fine yes

thheller10:06:15

but if you require @material-ui/core you will require the "meta" package

p-himik10:06:27

Ah, I see.

thheller10:06:30

which includes EVERY component the package provides

thheller10:06:38

so it adds about 1.2mb to you JS

thheller10:06:44

which can't the DCE'd yet

thheller10:06:00

so you should avoid doing that unless you are actually using all of them

thheller10:06:38

if you don't care about size then :refer is not very useful on its own

p-himik10:06:46

And I guess Shadow-CLJS can't just magically turn :refer-like :require to a :default-like one, right?

thheller10:06:17

yes that is not currently supported

p-himik10:06:54

I mean in principle, given the mess in the way different packages export stuff.

James Acklin19:06:37

hello! this is perhaps an elementary question, but i am attempting to require a JS (react) module relative to the current namespace as outlined in the docs (https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js). i'm unable to get relative paths working (`shadow$provide is not defined`), but if i drop the js module in node_modules, it seems to resolve. are there special considerations i'm perhaps overlooking? i am not importing from the same directory, so i may not fully understand what is meant by "This is unlike node which expects relative requires to always resolve to physical files." thank you!

thheller20:06:00

@james.acklin do you have more details? which version do you use? which build target? build config?

thheller20:06:10

what does the JS do?

Mudge20:06:47

Once I watch a build with shadow-cljs is there a way to unwatch it without shutting down the server?

James Acklin20:06:48

i am using shadow-cljs 2.8.37, the :npm-module build target (which is then imported by storybook-react), and the JS exports a function which returns an SVG with a bunch of child paths

James Acklin20:06:33

from shadow-cljs.edn:

:stories {:target :npm-module
            :output-dir ".storybook-compiled"
            :devtools {:enabled false}}

thheller20:06:37

hmm :npm-module might not support that style of js require

James Acklin20:06:33

i also control this library, so i may just implement a pure clojurescript variant just to keep things simple

thheller20:06:39

it might work if you use ES6 style import/export

James Acklin20:06:54

okay, i will try that as well

thheller20:06:14

it might be possible to get this to work with npm-module. I never tried before

thheller20:06:30

npm-module has all sorts of special cases 😛

James Acklin20:06:50

yes! others on my team are discovering that as well

James Acklin20:06:56

thanks for the help and for the excellent tool

dabrazhe21:06:13

Hi. Does anyone has a template or sample shadow-cljs project for AWS lambda deployment with Serverless Framework ?

richiardiandrea22:06:25

I don't have a template, but it is very simple - I am using:

{:source-paths ["lambda-src"]
 :builds {:aws {:target :node-library
                :exports {:handler ingest-events.aws/handler}
                :output-to "ingest-events/index.js"
                :js-options {:js-provider :shadow
                             :keep-native-requires true}
                :release {:compiler-options {:source-map true
                                             :optimizations :simple}}}}}