Fork me on GitHub
#shadow-cljs
<
2019-11-20
>
Eliraz09:11:36

how would you setup the hot replacement ?

Eliraz09:11:42

hot reload

Shuai Lin09:11:14

@thheller When targetting :node-script, does shadow-cljs provides some way to bundle all the code (including all npm deps) into one js file (for easier distribution)?

Heikki Hämäläinen10:11:08

I am using shadow-cljs in Gitlab enviroment where it is not possible to cache directories which are outside build directory (for example $HOME/.m2). What is the preferred way to set .m2 directory location?

thheller10:11:56

assuming you are actually using shadow-cljs.edn and not project.clj/deps.edn you can set :maven {:local-repo "maven"} or so in shadow-cljs.edn

thheller10:11:05

that should put it all in the project directly

Heikki Hämäläinen10:11:29

Yes, this seems to work. Maybe this can be added to user guide as well because some one else may find the same problem as well

Heikki Hämäläinen11:11:15

One more question. Do I understand correctly that --config-merge cannot be used to merge configuration to root level of shadow-cljs.edn but only inside :builds -> :build-name map?

thheller11:11:36

yes, that is for merging build config only

thheller11:11:07

you can set the maven config in ~/.shadow-cljs/config.edn

thheller11:11:30

but maybe that doesn't work on gitlab? not sure?

Heikki Hämäläinen11:11:56

I think that it might work because I can create that file in the build pipeline. I will try and see what happens.

orestis13:11:41

Using 'shadow-loader' (or more accurate, shadow-lazy), can I set up so that modules are loaded from an absolute URL and not from the "current" origin?

thheller13:11:43

:asset-path controls that, just stick the entire URL in there

orestis13:11:44

ok, I'm calling release from Clojure, and I need to override the asset path. Should this work? (shadow/release :main {:asset-path "something"})

thheller13:11:50

why not put it into the config directly?

thheller13:11:12

:release {:asset-path "//foo.com/js"}?

thheller13:11:20

or is it dynamic in some way?

orestis13:11:05

It's dynamic, yes -- we unfortunately have a couple of environments and a semi-complicated setup.

thheller13:11:34

(shadow/release :main {:config-merge [{:asset-path "something"}]})

orestis13:11:47

Works, thanks!

orestis13:11:38

A lazy module that works well in development, fails to load in release mode. The error is something like shadow-cljs - failed to load – 329, how to debug this? is this a case for pseudo-names?

orestis13:11:11

or I guess --debug ?

orestis14:11:32

ok, making some progress -- loading the module as a script, I get $jscomp is not defined, which I see in the main module wrapped inside an IIFE, so that's probably the culprit

Eliraz14:11:16

I keep getting your not viewing the latest compilation output

Eliraz14:11:37

why is that?

Eliraz14:11:37

I mean, I was not able to setup the hot-reload properly

orestis14:11:53

@eliraz.kedmi are you using the built-in shadow http server or your own? That error is usually a stale cache problem.

Eliraz14:11:05

I'm using the built-in.. maybe it's the way I'm using it? I simply jack-in using CIDER with nRepl

orestis14:11:39

Are you starting a shadow watch build somehow?

Eliraz14:11:55

I'm not sure that's the proper way to activate the hot reload. however, when I change the code I do see the little CLJS logo spins and nothing changes

Eliraz14:11:29

I don't know, when I start I get into the repl and the server is up and running

orestis14:11:08

Do you change the code via editing a .cljs file and saving?

orestis14:11:16

Or by evaluating a function at the repl?

Eliraz14:11:04

I change a file and save

Eliraz14:11:38

I see that CLJS icon appears spins (like it's doing some calculations) and goes away

Eliraz14:11:45

but nothing actually changes on the DOM

orestis14:11:02

OK, and have you setup a function in your project to be called after load? i.e. something with ^:dev/after-load metadata?

Eliraz14:11:59

No, I have not. I don't know what that function suppose to do? I mean, what logic to put inside it?

orestis14:11:42

Are you using reagent? If so you'd probably call (reagent/render ...), most probably the function you call to start your applicaiton.

orestis14:11:47

Shadow doesn't know what to do when it reloads your code -- you might have changed component but shadow tries to be framework agnostic. So it will put the new code in the browser, but you somehow need to re-render the DOM yourself. That's where these build hooks come in.

Eliraz14:11:36

got it, so the start function

Eliraz14:11:45

I'm actually using hx

Eliraz14:11:59

I want to leverage the new hooks API

orestis14:11:28

(defonce EL (atom nil))
(defn ^:dev/after-load -render []
  (when @EL
    (react-dom/render
     (hx/f [Main])
     @EL)))

Eliraz10:11:58

using this method will keep the state of the app while reloading?

Eliraz10:11:17

also, what is the Main function?

orestis11:11:20

Regarding state of the app, that's a question of how you set it up. If it's global state that lives under a defonce then yes. If it's local state (react hooks) it will be gone.

orestis11:11:30

The Main is just the root component in that case.

Eliraz13:11:41

got it. thank you

orestis14:11:46

That's what I use, with some weird hack to get the element

orestis14:11:02

Feel free to jump into #hx

orestis14:11:59

So I'm trying to figure out what's the deal with my $jscomp issue -- I see a bunch of code in my lazy module that does things like $jscomp.arrayFromIterable, $jscomp.makeIterator and so on -- but no $jscomp definition in it. The main module almost immediately starts with

(function(){
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl .... 

orestis15:11:23

So the docs say (https://shadow-cljs.github.io/docs/UsersGuide.html#output-wrapper): "When using multiple :modules (a.k.a code splitting) this is not enabled by default since each module must be able to access the variables created by the modules it depends on." -- but it seems that's not entirely true. If I turn set :output-wrapper false then I get over my issue, $jscomp is public and everything works again, with the downside of having a ton of global variables.

thheller15:11:32

@orestis yeah what is an issue I've been meaning to look into. you can fix it by either :output-wrapper false or :prepend-js "var $jscomp = {};" in the base module to pull it into the global scope

thheller15:11:13

for some reason when using output-wrapper the var $jscomp just becomes $jscomp that isn't exported

orestis15:11:38

Are you sure about the :prepend-js ? It doesn't seem to work, and I don't see how it could since it would run through optimisations. I tried :prepend to get it as a plain string but apparently due to JS scoping rules, the IIFE expression will still not "see it".

thheller15:11:09

might only work with :prepend not :prepend-js

thheller15:11:31

but it should work with one of those

orestis15:11:04

:append "window.$jscomp = $jscomp;

orestis15:11:07

seems to do the trick

orestis15:11:28

append puts it inside the IIFE, prepend makes it go outside

thheller15:11:16

I'm not sure why this is necessary at all though. especially since :advanced should be renaming this but for some reason it doesn't

thheller15:11:07

it is a closure compiler thing though and kinda difficult to report

orestis15:11:23

Made an issue here: https://github.com/thheller/shadow-cljs/issues/603 for Google's sake

👍 4
jjttjj19:11:27

anyone happen to know of an example usign shadow-cljs with klipse? when i require the klipse namespaces in my namespace, I get the following error:

The required namespace "cljsjs.codemirror.addon.edit.closebrackets" is not available, it was required by "klipse/ui/editors/editor.cljs".
The namespace was provided via :foreign-libs which is not supported.
Please refer to  for more information.

I'm trying to shim that addon namespace as described in the shadow guide, but I'm having trouble figuring out the things i need to require and export. There's also a few more addons in that klipse namesace that will have to be shimmed.

donyorm19:11:58

So I'm still having issues with source-maps not actually working with shadow-cljs. The sourceMappingURL in a file appears to be a relative path, is that how's it supposed to work?

//# sourceURL=js/cljs-runtime/edu.unc.applab.clem.views.js
//# sourceMappingURL=edu.unc.applab.clem.views.js.map

thheller19:11:38

@donyorm as I said before this is controlled by :asset-path. if you set :asset-path "js" then yes it will be a relative path

donyorm19:11:53

ok I did set asset-path to js

donyorm19:11:23

This is my shadow-cljs.edn file now. But behavior is the same as before

thheller19:11:35

it should likely be /js otherwise your paths won't resolve properly as you use any kind of "routing"

thheller19:11:41

ie. if you load the page via /some/thing then the browser will try to resolve /some/thing/js

thheller19:11:54

with /js you force it to actually use /js

donyorm19:11:14

Ok let me try that

donyorm19:11:52

Changing it to /js didn't seem to do much. Here's the source map part of the file:

//# sourceURL=/js/cljs-runtime/edu.unc.applab.clem.views.js
//# sourceMappingURL=edu.unc.applab.clem.views.js.map

thheller19:11:26

can you please state your actual problem?

thheller19:11:32

that looks exactly like it should?

donyorm19:11:37

The source map is at /js/cljs-runtime/edu.unc.applab.clem.views.js.map Will that setup find it properly

donyorm19:11:12

Basically firefox isn't using source maps in error reporting (and presumably shadow-cljs/react/whatever is sending errors to the console) isn't using them either. Ex. I'll get the following stack-trace:

cljs$core$IFn$_invoke$arity$6 /js/cljs-runtime/cljs.core.js:13306
    cljs$core$IFn$_invoke$arity$5 /js/cljs-runtime/cljs.core.js:13288
    cljs$core$IFn$_invoke$arity$4 /js/cljs-runtime/cljs.core.js:13276
    cljs$core$IFn$_invoke$arity$4 /js/cljs-runtime/cljs.core.js:13564
    list_errors /js/cljs-runtime/edu.unc.applab.clem.views.js:102
    res /js/cljs-runtime/reagent.impl.component.js:134
    reagent$impl$component$wrap_render /js/cljs-runtime/reagent.impl.component.js:153
    reagent$impl$component$do_render /js/cljs-runtime/reagent.impl.component.js:201
    render /js/cljs-runtime/reagent.impl.component.js:227
Which doesn't give me much help in where to look in my own file

thheller19:11:36

in which context is that thrown?

thheller19:11:43

I mean is it actually thrown or is it logged?

donyorm19:11:47

It's part of a reagent component running in re-frame

thheller19:11:14

ie. is something does console.warn(ex) then it won't have source mapping

thheller19:11:31

if it is actually uncaught it should be mapped

donyorm19:11:10

I think it's actually uncaught. I'll throw an exception in my own code just to be sure

thheller19:11:25

try something like

(js/setTimeout
  (fn []
    (throw (ex-info "omg" {})))
  2000)

donyorm19:11:27

It's possible react is catching something

thheller19:11:28

in your main code

thheller19:11:36

that is mapped fine for me in firefox

thheller19:11:26

if it is caught and logged I get a useless trace

thheller19:11:28

"Error: omg
    at new cljs$core$ExceptionInfo (/js/cljs-runtime/cljs.core.js:36930:10)
    at Function.eval [as cljs$core$IFn$_invoke$arity$3] (/js/cljs-runtime/cljs.core.js:36991:9)
    at Function.eval [as cljs$core$IFn$_invoke$arity$2] (/js/cljs-runtime/cljs.core.js:36987:26)
    at eval (/js/cljs-runtime/demo.browser.js:19:29)"

donyorm19:11:47

Now I'm getting this error

Source map error: Error: request failed with status 404
Resource URL:  line 827 > eval
Source Map URL: cljs.core.js.map
I wonder if my routing is messed up. Anyway for me to tell what url it's looking for the source-map at?

donyorm19:11:55

Thanks for the help by the way, I appreciate this

donyorm19:11:24

Missed the source map url

donyorm19:11:29

doesn't seem to be using the asset-path

thheller19:11:05

your config is fine but it appears you are using a custom webserver?

thheller19:11:14

(there is no config for that in the config you pasted)

thheller19:11:26

so what is running at localhost:3000?

donyorm19:11:48

Sorry forgot I was doing that separately

donyorm19:11:52

It's a ring webserver

thheller19:11:04

does it serve properly?

donyorm19:11:13

The code frontend and backend are running on the same machine so I needed to have ring server it up

donyorm19:11:30

And yes it does

thheller19:11:45

and you are accessing the page via http://localhost:3000?

thheller19:11:07

and the script is included via <script src="/js/main.js">?

thheller19:11:49

try setting :devtools {:loader-mode :script} in your build config

thheller19:11:36

doubt that changes anything but who knows

thheller19:11:21

firefox devtools are still kinda bad

donyorm19:11:23

That did it

thheller19:11:40

hmm that should not have done anything 😛

donyorm19:11:08

Well I'll roll with it for now. Thank you so much for the help

thheller19:11:00

guess I broke firefox somehow. hot-reload doesn't trigger at all anymore for me

donyorm19:11:37

It was being a little weird with me, but it's still working

thheller19:11:02

oh nvm .. just broke because I was messing with the compiler 😛

donyorm19:11:50

That would do. Seems to be working fine for me, other than the fact that my server is not serving the proper mimetype for JS files. Guess I'll have to fix that

thheller19:11:05

I'll try to figure out why it isn't loading the source maps anymore. It used to work fine the last time I tested in Firefox

thheller19:11:21

and it is still working fine if errors are thrown at runtime

thheller19:11:30

but no longer for anything logged while loading

thheller21:11:24

@aisamu I'm not able to reproduce the goog.math.Long error you ran into yesterday. is it possible you are including two separate builds using the closure library in some way?

aisamu21:11:53

Hmmm, I'm not sure. It's definitely not the goal

aisamu21:11:43

I'll dig some more, thanks for checking it 🙂

thheller21:11:44

I found one issue with :npm-module but I can't see how that possibly leads to your error

aisamu21:11:44

Would you like me to check for something in specific? (e.g. I'd expect multiple requires to be de-duped by webpack, for example)

thheller21:11:46

if anything they would be completely separate builds. can't see how it would include the same build twice

👌 4
thheller22:11:37

try 2.8.74, maybe that fixes it for reasons I can't explain 😛

aisamu11:11:18

Hahahah. Tried it but no luck 😕

aisamu19:11:42

Still can't explain the failure, but noticed two major changes while diffing the failing js bundle: Some TLD's are now wrapped in a parenthesis

- cljs.core._STAR_print_newline_STAR_ = false;
+ (cljs.core._STAR_print_newline_STAR_ = false;)
goog.math.Lang is wrapped/provided differently
;;;;;;;;;;;;;
;; Old

goog.provide("goog.math.Long");
...
goog.math.Long = function(low, high) { ...}
...
goog.math.Long.getMinValue = function() { ... } 

;;;;;;;;;;;;;
;; New

goog.loadModule(function(exports) {
  ...
  goog.module("goog.math.Long");
  ...
  var Long = function(low, high) {...}
  ...
  Long.getMinValue = function() { ... }
  ...
  exports = Long;
  return exports;
});
module.exports = goog.math.Long;
:man-shrugging: Will keep digging....

thheller19:11:16

looks normal

thheller19:11:52

the closure compiler/library moved to a new format for the goog.math.Long ns

thheller19:11:18

it works fine in the browser. maybe something weird going on for npm-module. it does work in node. I'll try to get a webpack test setup going

👍 4
aisamu19:11:45

OK! Thanks! I'll report back if I find something else

grounded_sage21:11:37

I got this funny experience where I can't compile tailwind in a shadow-cljs project.

grounded_sage21:11:11

npx tailwind build styles.css -o output.css This command works normally but inside a folder that has a shadow-cljs project it doesn't??

thheller21:11:10

and how does it fail?

thheller21:11:23

I use tailwind myself and had no problems so far?

grounded_sage21:11:50

It takes styles.css which is

@import "tailwindcss/base";

@import "tailwindcss/components";

@import "tailwindcss/utilities";
and outputs the same content into output.css

grounded_sage21:11:23

It doesn't actually create the styles. I remember you saying you used it so I don't see how this is happening.

thheller21:11:58

uhm the @import syntax requires postcss?

grounded_sage21:11:01

just a silly copy paste error

grounded_sage21:11:43

that's embarrasing haha