This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-11
Channels
- # adventofcode (31)
- # announcements (6)
- # babashka (5)
- # beginners (93)
- # calva (15)
- # cider (20)
- # cljs-dev (16)
- # clojure (159)
- # clojure-berlin (1)
- # clojure-dev (5)
- # clojure-europe (9)
- # clojure-italy (9)
- # clojure-losangeles (2)
- # clojure-nl (26)
- # clojure-spec (7)
- # clojure-uk (33)
- # clojurescript (54)
- # clojutre (5)
- # cursive (20)
- # datomic (23)
- # emacs (19)
- # events (1)
- # expound (1)
- # figwheel-main (1)
- # fulcro (104)
- # hyperfiddle (1)
- # jobs (1)
- # luminus (10)
- # malli (59)
- # nrepl (1)
- # off-topic (11)
- # pathom (5)
- # planck (15)
- # reagent (13)
- # reitit (8)
- # rewrite-clj (10)
- # ring-swagger (3)
- # shadow-cljs (129)
- # tools-deps (46)
- # xtdb (14)
- # yada (1)
@wiseman maybe not the answer you want, but you can do it through deps.edn
š https://shadow-cljs.github.io/docs/UsersGuide.html#deps-edn
I am using cursive on a clj + cljs (+shadow-cljs) based project and I am aiming at a convenient way to get both repls up and jacked in - like running lein repl
, just connecting to a single port and throwing clj/cljs forms from the editor against that single nrepl service. I may be missing something, but I am really having a hard time getting there (ugly :init-ns
or even bypassing lein repl
and using lein run
instead).
How would you guys be doing this?
@cfleming IIRC - I had things working over a single repl session (with figwheel). Just had to switch the clj/cljs dropdown switch from time to time.
The issue with lein repl
was that I found no way to get everything up without a manual step in between (launching shadow/watch). Hence, I stepped back from running lein repl
and started fiddling with lein run
. However, I guess putting it all together may do the trick but still appears painful.
Don't know if it helps, but I run one repl for backend and one for shadow. to keep things fast, i set up a clojure.main run configuration in cursive and put the path to a file containing this in the parameters:
(require
'[shadow.cljs.devtools.api :as api]
'[shadow.cljs.devtools.server :as server])
(server/start!)
(api/watch :app)
(api/repl :app)
That kicks off the shadow compilation right there in the repl, and means i can restart shadow with a single click.seems like it might be possible to kick off your backend in that same script file as well? i don't think you'd be able to access its clj repl though
What does this error hint at? The result of a goog.define call must be assigned as an isolated statement.
Only getting it at release build
@schpaencoder bad closure-library
version on the classpath that is incompatible with the shadow-cljs version you are using
should be these
[com.google.javascript/closure-compiler-unshaded "v20191027"]
[org.clojure/google-closure-library "0.0-20191016-6ae1f72f"]
[org.clojure/google-closure-library-third-party "0.0-20191016-6ae1f72f"]
@thheller, oh, you mean the globally installed is in conflict with the project specific
dunno you should only be getting this error when using project.clj or deps.edn to manage dependencies?
those are dependencies you wouldn't normally specify but somehow you are getting different versions
"user-namespace was evaluated"
[:fb] Compiling ...
Closure compilation failed with 18 errors
--- goog/array/array.js:42
The result of a goog.define call must be assigned as an isolated statement.
--- goog/array/array.js:50
The result of a goog.define call must be assigned as an isolated statement.
--- goog/asserts/asserts.js:48
The result of a goog.define call must be assigned as an isolated statement.
--- goog/base.js:213
The result of a goog.define call must be assigned as an isolated statement.
--- goog/base.js:236
The result of a goog.define call must be assigned as an isolated statement.
--- remaining errors ommitted ...
relevant section from project.clj:
:builds {;; "firebase integration"
:fb {:target :browser
:compiler-options {:infer-externs :auto}
:output-dir "resources/public/fb/js"
:asset-path "/js"
:infer-externs :yes
:modules {:fb {:init-fn fb.core/init!
:entries [fb.core]}}
:build-hooks []
:release {:compiler-options {:optimizations :simple}}
:devtools {:http-port 8050
:http-root "resources/public/fb"
:watch-dir "resources/public/fb" :preloads [re-frisk.preload]}
:dev {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}}}
Hi!
Should we expect source-maps to work for :npm-module
targets?
They appear to be almost correctly generated, both for development and release.
For development (`compile`), the source-maps aren't taking into account the shimming preamble. Deleting that and inspecting the maps with source-map-visualization[1] works as expected:
Here's an example of what I'm calling a preamble:
var $CLJS = require("./cljs_env");
var $jscomp = $CLJS.$jscomp;
require("./cljs.core.js");
var module$shadow_js_shim_module$$material_ui$styles$ThemeProvider=$CLJS.module$shadow_js_shim_module$$material_ui$styles$ThemeProvider || ($CLJS.module$shadow_js_shim_module$$material_ui$styles$ThemeProvider = {});
[...]
var shadow=$CLJS.shadow || ($CLJS.shadow = {});
[...]
var module$shadow_js_shim_module$$material_ui$icons$StarHalfRounded=$CLJS.module$shadow_js_shim_module$$material_ui$icons$StarHalfRounded || ($CLJS.module$shadow_js_shim_module$$material_ui$icons$StarHalfRounded = {});
// empty line
$CLJS.SHADOW_ENV.setLoaded("cljs.namespace.js");
// empty line
Source maps for :browser-test
worked out of the box!
(I couldn't check release builds - the tool complained about missing sources)
[1] - https://sokra.github.io/source-map-visualization/#customIs it correct that shadow-cljs doesn't have configurable dev and release dependencies, because they're not needed in CLJS? I ask because this library provides two versions, in order to elide logging code in production: https://github.com/philoskim/debux#two-libraries
@tslocke yes that is true and you need to use deps.edn or project.clj for that. unfortunately the debux library was written in a "bad" form that requires switching dependencies when it could have been written in a much "cleaner" style that didn't require that
@aisamu I don't know about source maps. they are supposed to work BUT it is entirely depending on the tools to use when including that output somewhere else. since they are very likely going to process the JS again they need to take the "input" source maps (generated by shadow-cljs) into account when generating their own source maps for the output they produce
Yup! Those for :browser-test
work flawlessly, but those for :npm-modules
do not.
They're loaded and served correctly (via source-map-loader
on webpack) but the mappings are slightly off, and removing the preamble from the JS seems to fix the mapping (but breaks the file, of course)
We never brought it up because we were using WP3 at the time, and attributed it to it!
feel free to open an issue. I'll try to figure it out when I have a bit of time
it should be accounting for the "preamble" already but maybe thats not accurate anymore
Yup! Those for :browser-test
work flawlessly, but those for :npm-modules
do not.
They're loaded and served correctly (via source-map-loader
on webpack) but the mappings are slightly off, and removing the preamble from the JS seems to fix the mapping (but breaks the file, of course)
We never brought it up because we were using WP3 at the time, and attributed it to it!
@thheller it seems like you and @plexus talked about making Kaocha work with shadow-cljs back last january https://github.com/lambdaisland/kaocha-cljs/issues/2
did you think more about how it could work?
is this something that could work with just the provided shadow-cljs node-repl without any changes to shadow-cljs?
I was trying to figure out if it could power Calvas testing commands (e.g. "run this test") for cljs codebases
cljs.test is also kinda of a sore spot for me since the entire implementation is so needlessly complex ... uses way too many macros when it doesn't have to
If I do a release
build while running a watch
build, won't they conflict (ie mess up the development process), if I don't have a specific :release {:output-to "...
clause in my configuration? (`:target :browser`)
but the watch and release themselves won't interfere with each other during compilation
@thheller Is there a way to have builds spit out a native executable using nexe? Obviously I could just run it myself after the build. See https://clojurescript.org/guides/native-executables
Hello! I see a section on https://shadow-cljs.org/ about using shadow.resource
for non-code resources. I think this is meant for single files only. What approach would I use to require a directory instead?
yeah, you run that separately. you can build a hook to do that if you want if needed
Ok, thanks. Is there a way to get all the files in a directory?
Is it possible to see the output of the final configuration if your using the :config-merge option? Specifically if i run
(shadow/release <build-id> {:config-merge [{compiler-options {:optimizations :advanced}]})
I expect the build to use a configuration similar to as if i had a shadow-cljs.edn:
{:builds {<build-id> {:release {:compiler-options {:optimizations :advanced}}}
It would be nice to be able to easily verfiy i merged correctly.
yeah thats about it. if you merge something complicated you are probably doing something you shouldn't be doing š
My hesitation is because its not clear what the entry point of the merge is. The entire shadow-cljs.edn map or are we starting at the release key of the build A) root B) -> <build-id> :release
so (shadow/release <build-id> {:config-merge [{compiler-options {:optimizations :advanced}]})`
given a shadow-cljs
{:builds {<build-id> {:release {:compiler-options {:optimizations :simple}}}``
would be:
{:builds {<build-id> {:release {:compiler-options {:optimizations :advanced}}}
?
you only have {:build-id <build-id> :release {:compiler-options {:optimizations :simple}}}
so after the first step it only remains as {:build-id <build-id> :compiler-options {...}}
config merge is basically always merged last so you can be sure that those values are used
Thanks thheller. You have been a tremendous help. I only hope that i can pay it back at some point š.
Were observing some unexpected behavior when trying to do some code splitting. This is a different issue then what i asked about yesterday. The questions from yesterday were because i was trying to gather more information about this issue. The issue stated directly is that when we split out a module the client fails to correctly load that module. The specific details of what i'm observing are below. So originally (prior to the app being in a buggy state) we have a shadow-cljs.end that looks like this:
##NOTE "..." just means information we can ignore.
{:modules
{:main {...}
:a {:entries [...] :depends-on #{:main}}
:b {:entries [...] :depends-on #{:main}}}
This results in
the main module including a namespace (will call it c_ns).
The issue is that this namespace is really only a requirement of the a and b namespace (corresponding to the modules we declare above).
Its my understanding that if i explicitly create a new module for c_ns then have the other two modules (:a and :b) depend on it. Then
the c_ns wont be fetched as part of loading the main module. This is possible because once the modules depend on the namespace explicitly,
the Google Closure compiler will know to not put it in the default module (main).
Specifically if we make the shadow-cljs file such that its like this:
{:modules
{:main {...}
:a {:entries [...] :depends-on #{:main :c}}
:b {:entries [...] :depends-on #{:main :c}
:c {:entries [...] :depends-on #{:main}}}
This process seems to work when applied to the first module we tried it on.
However, on the second one we tried. It doesn't.
In the working version what we see from our network traffic on the browser is. The app loads and
we make a GET request for the module we split out. The react components correctly load and
everything works as expected.
In the version that DOESNT work. The app loads and makes 3 GET requests for the module we split out (possible retries). The
react components don't correctly load. Specifically, a component that was loaded as part of react suspense
never loads. Its stuck at "suspended = true". This component would correspond to module :a or :b (from above). The components
that depend-no the module we are trying to split out.
Additionally, This behavior is only observed when we use the compiler optimizations set to Advanced.
Which in part is making it difficult for me to understand how to debug the issue, as i'm less sure how to get feedback.@drewverlee you are overcomplicating your description a bit and at the same time missing important details š
assuming that your HTML page only includes <script src="/js/main.js">
or whatever path you have?
@thheller
Yes our HTML page includes <script src="/js/main.js">
For the module that isn't working were not using anything from shadow.loader. We were under the impression that just by declaring the modules in our shadow-cljs.edn file they would be re-organized as part of an optimization by the google closure compiler.
@thheller https://github.com/thheller/shadow-cljs/blob/2bceed2b6ac3b8cf5cae110d319553394aba8156/src/main/shadow/lazy.cljs#L28 This comment is probably relevent to our situtation. At least to understanding the feedback were getting. What specifically does it mean "when the eval failed"
Its also probably relevent that we have module-loader set to true
so just loading things eagerly. all the async loading stuff just complicates debugging
if all that loads fine you can try the async stuff but debugging load issues otherwise is pretty painful
For the module that is causing an issuue. I have tried both loading using the lazy component macro, which calls shadow lazy load. We also tried it without calling any shadow loader code directly, as we were under the impression that breaking them into modules was sufficient. The might be incorrect. Your suggesting I add logging around the shadow.lazy/load? I'll try including the modules directly in the HTML, thanks!
kinda hard to make suggestions since I know so little about what you are actually doign
Thanks. We dont have async enabled. I assume that makes it less likely there are issues.
Yes, i see what you mean. I was refering to that we dont have the async attribute enabled in our script tag when we load the main.js file.
So we added the module that was causing the issue to index.html.
@thheller
What i see from my dev tools console is: "Uncaught TypeEroor: cannot read property of 'prototype' of undefined."
at spec/alpha.cljs:1300
at shadow/module/<offending module>/append.js:2
append.js is just : shadow.loader.set_loaded();
So my interpretation of that is that somehow set_loaded is being called with no arguments? Possible resulting in the above error. Does that seem reasonable?
version "2.8.74"
yep will do.
I tried with .83 It seemed to have no effect on what happened.
Iām having an issue which I canāt reproduce with a minimal case, but goes away if I change the version of shadow Iām using. It seems unrelated to the build or the compiled files (Iāve removed the compiled files and restarted the build). Question is, is there some cache I can clear out outside of those things?
using st/instrument
for some reason it starts to return an empty vector and stops instrumenting my fdefs
I dropped back a version of shadow-cljs and it started working again, but eventually stopped, so I bumped the version and again it worked. Really frustrating as I cannot see why it would stop working.
that is strange. it sounds like it might have to do with the build/analyzer caching? Not sure
there is another dir, .shadow-cljs
, which has a builds
dir that has the build cache
it is typically verboten to remove this as it shouldnāt be necessary, but if clearing that out solves it, it might point us in the right direction to why itās doing this
@U4YGF4NGM nuking .shadow-cljs
made it work again
Them failing seems completely unrelated to the code though, I had removed some changes to see if those had caused it before deleting .shadow-cljs
and now have reintroduced it and everything is working fine :man-shrugging:
So your tests namespace instrument the functions inside the implementation namespace?
Itās like:
impl.cljs
<= defnās
impl_specs.cljs
<= fdefs
impl_test.cljs
<= st/instrument
code wise I canāt pin it to anything Iāve done. just working on files, saving, tests autorefresh and run. At some point the tests stop working and I log st/instrument and itās an empty vector.
something weird is that sometimes when I call st/instrumentable-syms
itās a set, other times it`s a vector, and when things werenāt working I remember running it and it was a vector with a ton of duplicates of the fdefāed syms
https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/spec/test/alpha.cljc#L69 it looks like calls to instrument mutate some global state in the running compiler process, which probably doesnāt play well with the way namespaces are cached while building
Iām not sure how this works in the vanilla cljs compiler, but I think an issue could be opened to fix this in spec.test
@U4YGF4NGM open an issue against ClojureScript itself?
https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/spec/test/alpha.cljc#L69 it looks like calls to instrument mutate some global state in the running compiler process, which probably doesnāt play well with the way namespaces are cached while building