Fork me on GitHub
#shadow-cljs
<
2022-11-22
>
qqq03:11:52

Why does shadow-cljs ignore :foreign-libs . See "unsupported" under section https://shadow-cljs.github.io/docs/UsersGuide.html#compiler-options

Anders Eknert10:11:10

Hey 🙂 After bumping shadow-cljs from 2.20.10 to 2.20.11 or 2.20.12, I get an error when building (via lein):

IllegalArgumentException: No matching method legacySetOutputFeatureSet found taking 1 args for class com.google.javascript.jscomp.CompilerOptions
	clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:127)
	clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:102)
	shadow.build.closure/set-options (closure.clj:166)
	shadow.build.closure/set-options (closure.clj:122)
	shadow.build.closure/convert-goog* (closure.clj:2295)
	shadow.build.closure/convert-goog* (closure.clj:2260)
	shadow.build.closure/convert-goog (closure.clj:2439)
	shadow.build.closure/convert-goog (closure.clj:2389)
	shadow.build.compiler/maybe-closure-convert (compiler.clj:1237)
	shadow.build.compiler/maybe-closure-convert (compiler.clj:1230)
	shadow.build.compiler/compile-all (compiler.clj:1472)
	shadow.build.compiler/compile-all (compiler.clj:1349)
	shadow.build.api/compile-sources (api.clj:261)
	shadow.build.api/compile-sources (api.clj:253)
	shadow.build/compile (build.clj:512)
	shadow.build/compile (build.clj:493)
	shadow.cljs.devtools.api/compile* (api.clj:296)
	shadow.cljs.devtools.api/compile* (api.clj:292)
	shadow.cljs.devtools.cli-actual/do-build-command (cli_actual.clj:34)
	shadow.cljs.devtools.cli-actual/do-build-command (cli_actual.clj:25)
	shadow.cljs.devtools.cli-actual/do-build-commands (cli_actual.clj:49)
	shadow.cljs.devtools.cli-actual/do-build-commands (cli_actual.clj:38)
	shadow.cljs.devtools.cli-actual/main/body-fn--17900--auto----18609 (cli_actual.clj:166)
	shadow.cljs.devtools.cli-actual/main (cli_actual.clj:165)
	shadow.cljs.devtools.cli-actual/main (cli_actual.clj:132)
	clojure.core/apply (core.clj:671)
	clojure.core/apply (core.clj:662)
	shadow.cljs.devtools.cli-actual/-main (cli_actual.clj:219)
	shadow.cljs.devtools.cli-actual/-main (cli_actual.clj:217)
	clojure.lang.Var.applyTo (Var.java:705)
	clojure.core/apply (core.clj:667)
	clojure.core/apply (core.clj:662)
	shadow.cljs.devtools.cli/-main (cli.clj:75)
	shadow.cljs.devtools.cli/-main (cli.clj:67)
	clojure.lang.Var.invoke (Var.java:388)
	user/eval140 (form-init17017545089428182543.clj:1)
	user/eval140 (form-init17017545089428182543.clj:1)
	clojure.lang.Compiler.eval (Compiler.java:7194)
	clojure.lang.Compiler.eval (Compiler.java:7184)
	clojure.lang.Compiler.load (Compiler.java:7653)
	clojure.lang.Compiler.loadFile (Compiler.java:7591)
	clojure.main/load-script (main.clj:475)
	clojure.main/init-opt (main.clj:477)
	clojure.main/init-opt (main.clj:477)
	clojure.main/initialize (main.clj:508)
	clojure.main/null-opt (main.clj:542)
	clojure.main/null-opt (main.clj:539)
	clojure.main/main (main.clj:664)
	clojure.main/main (main.clj:616)
	clojure.lang.Var.applyTo (Var.java:705)
	clojure.main.main (main.java:40)
no other changes made, and reverting “fixes” the issue… I tried searching here but didn’t see any mention of this

thheller10:11:24

@anders982 you probably have a pinned closure-compiler version. so a dependency conflict. needs the newest version

Anders Eknert10:11:37

Hmm, not to my knowledge, but maybe something else is pulling it in. I’ll take a look, thanks!

Anders Eknert12:11:22

ah, in clojurescript itself 🙂 thanks again 👍

Quentin Le Guennec13:11:51

Can I specify the shadow-cljs build with the command clojure -X shadow-cljs/release ?

thheller13:11:28

no, but you can run clj -M -m shadow.cljs.devtools.cli release app

Quentin Le Guennec13:11:30

Perfect, thank you for the quick answer

grav21:11:51

How come :release doesn't support {:optimizations :none}? In case of node-script, I imagine it might make sense to avoid any code size optimization (ie skip the Closure compiler), but still strip out all the development related code.

thheller21:11:27

thats what :compile is

thheller21:11:38

otherwise use :simple

thheller21:11:03

:compile still has all the debug loader mechanisms and stuff and just is not a release build by any means

grav07:11:26

So there isn't any way to avoid running the closure compiler, but still strip out development related code?

thheller07:11:09

define what you mean by "development related code"?

thheller07:11:51

the whole emitted code could be considered development related code unless it runs through the closure compiler

grav07:11:16

> development related code Yeah, that's a good question. Honestly I just took that phrasing from the docs: https://shadow-cljs.github.io/docs/UsersGuide.html#_release_mode

grav07:11:38

You alkso mention "debug loader mechanisms", I guess that's part of it?

thheller07:11:11

ok, I define development related code as: code injected by shadow-cljs that is not otherwise specified by your build config. ie. the websocket connection for repl/hot-reload

thheller07:11:16

watch injects those

thheller07:11:19

compile does not

thheller07:11:35

then further "development code" is the goog.require and goog.provide calls

thheller07:11:44

which both of these contain

thheller07:11:08

release will remove those and also collapse the many input files into the configured output file(s)

thheller07:11:34

so, watch/compile are forced to be :none as it never runs the closure optimizations

thheller07:11:52

release will ALWAYS optimize, therefore it makes no sense to allow :none here

thheller07:11:27

watch/compile code is also meant to never run anywhere else than the location output by shadow-cljs

thheller07:11:40

so its not guranteed to work when copied or integrated into other things

grav07:11:25

Okay, I think I follow, apart from the last two comments. Say I want to run a nodejs app in a lambda or similar. If I wanted the "cleanest" code, eg for understanding a stack trace in production, wouldn't it make sense to use the output from compile?

thheller07:11:29

use source maps?

thheller07:11:50

I don't think understanding a stacktrace of none compiled code is very easy. source maps make that easy

thheller07:11:21

you can also sort of use --pseudo-names I guess. that gives sort of legible names for :advanced output, but still source maps are the solution here

grav07:11:39

Yeah, sounds about right. In the browser I'm used to the browser magically doing all the source mapping for me. In the context of lambdas, I'm usually trying to infer stuff from small snippets of stack traces in cloud watch logs - which is definitely not the way to go.

grav07:11:40

Do you have any pointers on how a workflow with sourcemaps outside the browser would look?

thheller07:11:45

but besides all that :simple is just as readable as :none is

👍 1
thheller07:11:05

:compiler-options {:source-map true}

thheller07:11:20

the rest all depends on what kind a runtime you use

thheller07:11:25

some pick up the maps automatically

thheller07:11:32

some might need to be coerced

thheller07:11:38

some will not support it at all

grav07:11:44

Alright - I guess minified javascript is not unusual in a Lambda. I'll see what I tooling can dig up. Thanks a lot for the pointers!

thheller07:11:14

minified code should indeed be the norm

qqq21:11:52

does compiler warnings prevent the the hot reloading of ^:dev/after-load fns ?

thheller21:11:47

yes. you can set :devtools {:ignore-warnings true} in the build config, but fixing warnings should be the first choice

👍 1
colinkahn23:11:34

Are these equivalent ways to pass in additional config for release:

lein shadow release app --config-merge '{my.ns/HOST ""}'

 (shadow/release :app {:closure-defines {'my.ns/HOST ""}})
I'm seeing the first one work, but the second doesn't.

colinkahn23:11:02

Figured it out (shadow/release :app {:config-merge [{:closure-defines {'my.ns/HOST ""}}]})

👍 1