This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-06-20
Channels
- # beginners (94)
- # boot (8)
- # cider (21)
- # cljs-dev (3)
- # cljsjs (5)
- # cljsrn (10)
- # clojure (167)
- # clojure-italy (4)
- # clojure-norway (1)
- # clojure-russia (9)
- # clojure-spec (25)
- # clojure-uk (29)
- # clojurescript (20)
- # cursive (12)
- # datomic (55)
- # emacs (10)
- # fulcro (16)
- # graphql (1)
- # hoplon (18)
- # lein-figwheel (30)
- # off-topic (259)
- # onyx (8)
- # other-languages (13)
- # re-frame (1)
- # reagent (62)
- # ring (8)
- # ring-swagger (28)
- # shadow-cljs (187)
- # spacemacs (15)
- # specter (2)
- # testing (12)
- # tools-deps (38)
I also had, in my shadow-cljs.edn
file
:lein {:profile "cljs"}
adding the dependencies to the cljs profile in project.clj
made the warning go away for cider-nrepl
, which is good enough for now,any idea what needs to be done for clj-refactor
? i still get
WARNING: clj-refactor and refactor-nrepl are out of sync.
Their versions are 2.4.0-SNAPSHOT (package: 20180420.223) and n/a, respectively.
I think that shadow-cljs automatically loads the cider-nrepl middleware if it detects it on the classpath. I don’t think it does the same for clj-refactor
there’s a place in the userguide about adding nrepl middleware to shadow-cljs: https://shadow-cljs.github.io/docs/UsersGuide.html#nREPL
so you’ll need to add
{...
:nrepl {:port 9000
:middleware ['refactor-nrepl.middleware/wrap-refactor]}
...}
I’m wondering if I’ve got my shadow-cljs configuration set up incorrectly. A couple issues
1. Slow: 5-15 seconds for live reload. This is on a very small project with 8 files. Reading other comments on this thread makes me think that this is typical.
2. Source maps: I think these are on by default, but I get so many errors where the component name isn’t exposed - it’s like it’s using a minified name. My problem is always with b
! Here’s a simple example
(defn stats-modal []
[:> sem/Modal {:trigger (reagent/as-element (stats-button))}
[:> sem/Modal.Content
[:p "example content"]]
])
Debugging it, I get different versions of this:
> Warning: Failed prop type: Invalid prop trigger
supplied to b
, expected a ReactNode.
> in b (created by permits.views.home.header.stats_modal)
> in permits.views.home.header.stats_modal (created by permits.views.home.header.header_bar)
> in div (created by permits.views.home.header.header_bar)
> warning.js:34 Warning: Failed prop type: Invalid prop trigger
supplied to b
, expected a ReactNode.
> in b (created by permits.views.home.header.stats_modal)
> in permits.views.home.header.stats_modal (created by permits.views.home.header.header_bar)
> in div (created by permits.views.home.header.header_bar)
> in div (created by permits.views.home.header.header_bar)
> The above error occurred in the <b> component:
> in b (created by b)
> in b (created by b)
This sometimes narrows it down to the React component, but for bigger components I have no idea where the problem is. That leads me to very small refactors where I check for errors in the rendering. But with slow reload times it feels impossible to be productive. Is there a source map option to get non-minimized errors? Or does that slow it down more?
Here is my shadow-cljs.edn
files:
{:source-paths ["src"]
:dependencies [[reagent "0.7.0"]
[re-frame "0.10.5"]
[binaryage/devtools "0.9.10"]
[day8.re-frame/re-frame-10x "0.3.2-react16"]
[bidi "2.1.3"]
[kibu/pushy "0.3.8"]
[cider/cider-nrepl "0.17.0"]
[soda-ash "0.81.1"]]
:builds {:app {:target :browser
:output-dir "public/js"
:asset-path "/js"
:modules {:main {:entries [permits.core]}}
:compiler-options {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}}
;; start a development http server
:devtools {:after-load permits.core/render
:http-root "public"
:http-port 8020
:preloads [devtools.preload day8.re-frame-10x.preload]}
:release {:output-dir "dist/js"}}}}
I run first npx shadow-cljs server
then npx shadow-cljs watch app
Ok, I’ll look at Reagent error messages. It looked like minimization, which I thought would be shadow-cljs role. I wonder why it’s so slow to reload
when thheller gets up he can help with that. try running your watch with the --verbose flag. that will give you some insight
you might be right about the minification. i think the :>
operator is setting the name of the component from the function name and the function name appears as though it is getting minified. that seems weird though, because i’m pretty sure thomas only runs node modules through simple minifications
node_modules
only run through :simple
yes but :simple
does include variable renaming by default wherever it can. :property-renaming
however is usually only used in :advanced
.
Ok. I’ll try the verbose flag
Hi, all. Currently, I am trying to migrate my lein cljs build to shadow-cljs. I find that the embed resource tricks stop working. May I know there is some workaround on this?
@albert.lai that indeed looks like a bug. will look into it.
@momoblackblack usually you should have source maps for everything but the error message looks like it might be generated by react so it might not use source maps. you can try setting :dev {:js-options {:variable-renaming :off}}
and/or :property-renaming :off
5-10sec is not normal. you can try running with --verbose
to get a bit more timing information. would be useful to know where the time is spent.
@currentoor if you use :lein
then :dependencies
in shadow-cljs.edn
are ignored. everything must be in project.clj
. no idea about emacs stuff.
@wilkerlucio currently there is no way to skip preloads for workers. still need to do a standalone worker build target. currently the worker module just loads all the sources of the modules it depends on without any filtering. not sure how easy it would be to filter.
@albert.lai fixed in 2.4.6
. btw if your CLJS namespace with the macro self requires (ns abc.cljs-embed (:require-macros [abc.cljs-embed]))
, you scan skip the :include-macros true
everywhere else
@thheller thanks! I will try it now!
Does anyone uses cljss
with shadow-cljs
? Did you solved cache busting, i.e. do your styles hot-reload?
@thheller is there a function for “release”ing, but rather than writing to disk, it returns some string a server can keep in memory?
@levitanong no, it always assumes you want to write to disk
@thheller yes, when i run the server, i do a number of things. For css, I compile via garden css (and then store the string in memory, so that whenever a request matches that css route, i shave a bit off my response time because i skip i/o. Plus, cachebusting is way easier) For js, I run shadow/release
.
dev mode is pleasant because i use stuartsierra’s component, so setup/teardown of shadow.server/start!
and shadow.server/stop!
so I’m just thinking, it would just be neat if i could do to js what i do for css.
running the entire shadow-cljs server in your production app may not be the best idea
how so?
it really is meant for development and launches a bunch of endpoints you really don't want to expose on a public server
but i’m not using that for production
i only run release
for production
and the shadow server stuff when my server is in dev mode
so i have another question:
is there any plan to support more profiles other than dev and release?
in my company, we have several stages our apps go through: development, testing, staging, a million other things, and then finally prod
it’s only in development that i want to run things in dev mode, the rest in release
so my stance on this is simple: everything beyond development should use the release profile
however, those other profiles should be using slightly different endpoints
but what about the google closure defines?
or is that me misusing that functionality? 😛
do you have any advice for endpoints? because i don’t really need them to be set at runtime.
ah, that is fascinating.
but what about API keys?
but wouldn’t that be exposing your API keys to the public?
’cause it’ll just be there in your script tag in “plaintext”
but it’s more accessible, isn’t it? 😛
that’s true
i guess that’s why domain constraints are there
yeah you don't get any more security by compiling the keys into your JS via closure defines
but if you put them into the closure defines you have to recompile whenever the keys change (eg. prod vs staging)
i like this
thanks @thheller! this was really helpful 😄
I use this approach since about 2012 or so https://code.thheller.com/blog/web/2014/12/20/better-javascript-html-integration.html
@thheller interesting. what is that cljs
function?
<script type="shadow/run" data-fn="my_app.feature1" data-ref="self">
{config: true,
data: big_json_blob_from_server}
</script>
okay, understood.
thanks again!
@wilkerlucio @bolasblack the 1.10.312
...spec/return
issue should be fixed in 2.4.6

I was a bit worried about that one, how did you manage to get around the js marking?
same way David did it https://github.com/clojure/clojurescript/commit/693cd0da6d89a4d3a583a9e78e68e458580b43cc
well, if works 😛
I hope it does. didn't actually verify with test.check
itself, just some test code I wrote
ok, I can verify that and let you know, will try now
Just wondering what you mean by this https://shadow-cljs.github.io/docs/UsersGuide.html#_build_tool_integration @thheller
I'm thinking of using the Clojure cli and layering on other tools to create something like Gatsby in respect of compiling to a PWA with PRPL pattern etc.
https://code.thheller.com/blog/shadow-cljs/2017/11/18/the-many-ways-to-use-shadow-cljs.html
I'm just curious about the caution you have there and what it really means.
Yea I have read that a few times. So you just mean that the other build tools can slow down the experience and get in the way yea?
if you use lein
or clj
directly they won't know about that server and start a new JVM
apart from that it has a few safeguards to avoid some dependency conflicts like accidentally using an ancient version of clojurescript
Well I am thinking for the most part there isn't any reason for using the clj for anything other than the full compilation step. When I want to do the SSR, Critical CSS inlining etc.
I'm just thinking of using the Clj-cli for SSR, Critical CSS inlining, image manipulation etc.
you could use shadow-cljs run your.tool/css-inline ...
instead of clj -m your.tool ...
so yeah if you build it for the clj
tool it will automatically work with shadow-cljs run
as well
Oh wow. I hadn't read that stuff before.
This looks easier than I thought it would be 😮
Ok that will learn me for not reading the full manual!
@thheller I tried using :variable-renaming :off
and :property-renaming :off
but still getting these obscured errors. So here’s an example error
warning.js:34 Warning: Failed prop type: Invalid prop `trigger` supplied to `b`, expected a ReactNode.
in b (created by permits.views.home.header.stats_modal)
in permits.views.home.header.stats_modal (created by permits.views.home.header.header_bar)
in div (created by permits.views.home.header.header_bar)
For this code:
(defn stats-modal []
[:> sem/Modal {:trigger (reagent/as-element stats-button)
:basic true}
[:> sem/Modal.Content
[:p "example content"]]
])
Here’s my config:
{:source-paths ["src"]
:dependencies [[reagent "0.7.0"]
[re-frame "0.10.5"]
[binaryage/devtools "0.9.10"]
[day8.re-frame/re-frame-10x "0.3.2-react16"]
[bidi "2.1.3"]
[kibu/pushy "0.3.8"]
[cider/cider-nrepl "0.17.0"]
[soda-ash "0.81.1"]]
:builds {:app {:target :browser
:output-dir "public/js"
:asset-path "/js"
:modules {:main {:entries [permits.core]}}
:compiler-options {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}}
:dev {:js-options {:variable-renaming :off
:property-renaming :off}}
;; start a development http server
:devtools {:after-load permits.core/render
:http-root "public"
:http-port 8020
:preloads [devtools.preload day8.re-frame-10x.preload]}
:release {:output-dir "dist/js"}}}}
the error is not wrapping the stats-button
. It should be (reagent/as-element (stats-button))
sem
is from ["semantic-ui-react" :as sem]
It might be. Ok. There is just no config that I know of in Reagent for that.
But I’ll look there
Warning: Failed prop type: Invalid prop `trigger` supplied to `Modal`, expected a ReactNode in Modal
@momoblackblack you might need to do (reagent/as-element [stats-button])
no that’s not the issue. there’s something funny going on with the way reagent imports components.
I did try that: [:> sem/Modal {:trigger (reagent/as-element [stats-button])
. No errors but the button doesn’t trigger the modal. Nothing happens. The only thing that works is [:> sem/Modal {:trigger (reagent/as-element (stats-button))
. Someone else said it’s maybe because of a hacky way react-semantic-ui set up those triggers that made it require a ()
@thheller using react-virtualized
imported like so [react-virtualized :refer [AutoSizer InfiniteLoader List]]
and running the following in the repl: (react/createElement AutoSizer #js {} (js-obj))
you get the Warning: Failed prop type: Invalid prop
children` of type object
supplied to b
, expected function
.
in b`
there’s that b
component again ^
@lee.justin.m you can see my config above after @thheller suggested it
:dev {:js-options {:variable-renaming :off
:property-renaming :off}}
btw, this does work: [:> sem/Modal {:trigger (reagent/as-element [:div [stats-button]])
. My issue wasn’t so much getting it to work, because I eventually got it to work through trial and error. I am just trying to make future debugging easier
the reason this happens is because reagent sets the display name of the component by using the .name
property of the component
so this value changes depending on that setting:
window.module$node_modules$react_virtualized$dist$commonjs$index.AutoSizer.name
"AutoSizer"
the closure documentation states that it does not change function names except in advanced compilation. how are you doing that if you are not in advanced?
@momoblackblack I would open up an issue on reagent about how [:> sem/Modal {:trigger (reagent/as-element [stats-button])}]
doesn't work
Reagent should check for a displayName prop so that it would work for nonfunctional components at least. Easy fix
does anyone have any examples of using shadow-cljs to compile clojurescript that can be pulled in as an npm dependency by regular javascript projects?
About this issue with react-semantic-ui. Turns out this is semantic-ui issue, not reagent
they take children and extend the props of the very top node with some additional hooks
onClick and something else
But if the top level node doesn’t accept these props, everythiing is going to be bad
so just wrapping reagent component into the native component resolves the issue:
:trigger (reagent/as-element [:div [stats-button]])
@nickmbailey I’m also looking for it today. This is the best example I found so far: https://github.com/loganpowell/shadow-proto-starter
Tested it, it works, not deployed to npm yet though
Here the dark magic happen for semantic-ui-react https://github.com/Semantic-Org/Semantic-UI-React/blob/43793ae59df9504131d1c9af4762a75321aa3ccc/src/addons/Portal/Portal.js#L445
They clone element and extend its prop
@denis_krivosheev yeah i maybe should have been more specific in that i’m targeting the browser specifically, from what i can tell that example is meant for node (maybe it works for both?)
@nickmbailey Denis was commenting on a previous issue
yeah he also linked an example for my question in the middle there though 🙂
Yeah. It’s hard to track several themes in the same chat 😃
@thheller you may be amused by this twitter thread https://twitter.com/dan_abramov/status/1009179550134296577
well we package some uncompiled cljs in there 😄
true, didn't expect that at all