Fork me on GitHub

is there a way to specify a git dependency in shadow-cljs.edn ?


@wiseman maybe not the answer you want, but you can do it through deps.edn 🙂


happy to help 🙂


Almost x-mas, right? 🎄 😉 ...


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-nsor even bypassing lein repland using lein run instead). How would you guys be doing this?


Cursive doesn't allow that if I understand you correctly


each connection can only be in one state CLJ or CLJS not both


so you'd have a secondary connection


(which is something I’m planning to fix, but have not got to yet).


which you can't start from purely clojure


@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 repland 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:

  '[shadow.cljs.devtools.api :as api]
  '[shadow.cljs.devtools.server :as server])
(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

[ "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?


shadow-cljs itself should never have this conflict when using only shadow-cljs.edn?


I’m using the lein-shadow plugin


those are dependencies you wouldn't normally specify but somehow you are getting different versions


check lein deps :tree


it'll tell you about conflicts


Got a ton of recommened exclusions, not sure what I am doing now


The first one was [org.clojure/clojurescript “1.10.520”]


okay, I think I’ll dabble with this first, thanks for the input


odd, the error prevailes


"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}}}


that section of project.clj is actually completely irrelevant 😛


it is only your :dependencies that matter here


somehow you are getting bad versions of the closure-compiler and/or closure-library


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;
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
// 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] -


Is 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:


@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

👍 1

Done! Thanks a lot!


but if the source maps generated by shadow-cljs don't match then thats a bug


it should be accounting for the "preamble" already but maybe thats not accurate anymore

Filipe Silva17:12:34

@thheller it seems like you and @plexus talked about making Kaocha work with shadow-cljs back last january

Filipe Silva17:12:03

did you think more about how it could work?


I did not no. didn't seem to fit very nicely into the entire system.

Filipe Silva21:12:48

is this something that could work with just the provided shadow-cljs node-repl without any changes to shadow-cljs?

Filipe Silva21:12:18

I was trying to figure out if it could power Calvas testing commands (e.g. "run this test") for cljs codebases


maybe? I can't remember any of the details really


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`)


they'll overwrite files yes


but the watch and release themselves won't interfere with each other during compilation


only the final output files


@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

Yosevu Kilonzo18:12:51

Hello! I see a section on 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


what would requiring a directory do?


but no its for separate files only

Yosevu Kilonzo18:12:41

Ok, thanks. Is there a way to get all the files in a directory?


not built-in no

👍 1

@thheller build hook looks like what I want, thanks!


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


you are starting with the build config, which already has :release or :dev merged


then your extra merges are applied


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}}} ?


scrap the :builds map that doesn't exist anymore


you only have {:build-id <build-id> :release {:compiler-options {:optimizations :simple}}}


:build-id is added automatically (taken from the outer map)


so after the first step it only remains as {:build-id <build-id> :compiler-options {...}}


then config-merge is merged in


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.
  {: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:
  {: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 😛


HOW you do you load modules?


assuming that your HTML page only includes <script src="/js/main.js"> or whatever path you have?


that uses shadow.loader?


@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 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 you are using shadow.loader. do you have errors during load?


they should be logged somewhere?


the easiest way to test is just including the modules directly in your html


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!


just add the three moduels in the proper order to your html


if that throws no error during load start testing the async load stuff


kinda hard to make suggestions since I know so little about what you are actually doign


code splitting can be tricky for sure


Thanks. We dont have async enabled. I assume that makes it less likely there are issues.


of course you have async enabled when using shadow.lazy. that is all async


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?


set_loaded takes no arguments so not thats not it


which version is this?


version "2.8.74"


can you try with either .83 or .68?


yep will do.


I tried with .83 It seemed to have no effect on what happened.


Is there any quick template with shadow-cljs including react as foreign-libs?


shadow-cljs doesn't even support foreign-libs so no 😛