Fork me on GitHub
#shadow-cljs
<
2019-01-10
>
orestis08:01:54

I’m observing something weird when using specs to validate a reagent atom — should I be careful when importing namespaces only for side effects (that is, to register specs etc)?

orestis08:01:46

My app.main (entry point) requires my app.state (and uses a bunch of functions) which in turn requires my app.spec — and uses nothing from there. However I get an error like so

main.js:3045 failed to load app.state.js Error: Unable to resolve spec: :base/count
    at Object.cljs$spec$alpha$the_spec [as the_spec] (alpha.cljs:121)
    at Function.eval [as cljs$core$IFn$_invoke$arity$5] (alpha.cljs:518)
    at Function.eval [as cljs$core$IFn$_invoke$arity$4] (alpha.cljs:513)
    at Object.cljs$spec$alpha$def_impl [as def_impl] (alpha.cljs:314)
    at eval (state.cljs:120)
    at eval (<anonymous>)
    at Object.goog.globalEval (main.js:2188)
    at Object.env.evalLoad (main.js:3043)
    at main.js:3261

orestis08:01:32

Where :base/count is defined in app.spec like so (s/def :base/count (complement neg-int?)) — and if I put that declaration in my app.state ns, the problem goes away.

orestis08:01:33

It’s my first time using spec from CLJS, so perhaps shadow CLJS might not be the culprit. I’m using :loader-mode :eval if it makes any difference.

orestis09:01:34

OK, got it — I had two shadow-cljs builds running — one for running the tests in node, one for the browser. Stopping them both and running only the browser one seems to fix things, :loader-mode :eval still works.

orestis09:01:53

Ouch, adding cljs.spec to the project hits me with a 60kb of optimized javascript. I guess DCE isn’t working in this case?

thheller12:01:22

@orestis yes spec is never DCE'd

thheller12:01:34

I opened https://dev.clojure.org/jira/browse/CLJS-1701 a while ago but nobody seems to care 😛

orestis12:01:43

Voted 🙂 — is there a workaround?

thheller12:01:14

nope. note that the 60kb is pre-gzip. gzip'd its not so bad.

orestis12:01:10

Yeah, but still, 20kb of gzip was like a 15% increase of my build. I’m not dying, but would be good to fix.

thheller12:01:43

can't really fix it. can maybe reduce it a bit but also not by much.

thheller12:01:01

only fix is not importing spec in the first place

orestis12:01:28

Yeah, I guess I can do that — but eventually I’d like to actually validate some things at runtime.

thheller12:01:10

then there is no way around it anyways

orestis12:01:25

Could be that the reason it’s not fixed yet is that people actually use it at runtime and gladly pay the price. I was a little bit surprised to see the gen.test stuff in there.

thheller12:01:54

it really cannot be fixed in the way it is written right now. so you basically need to rewrite the entire thing

thheller12:01:06

but that still doesn't guarantee that code can actually be removed

orestis14:01:55

@thheller I have to thank you (again) for coming up (and maintaining) shadow-cljs. It’s a fantastic tool. Please apply for Clojurists Together again.

denik15:01:58

@thheller looking into now builders, wondering if shadow-cljs supports all requirements to make one? https://zeit.co/docs/v2/deployments/builders/developer-guide/

denik15:01:44

here are builders for other langs: https://github.com/zeit/now-builders

thheller16:01:01

not sure if Java is available to builders? need the JVM to compile. besides that is should be easy to create a builder

denik16:01:43

I think it can be installed, see python and go

thheller16:01:00

not sure I understand what any of this does though 😛

denik16:01:23

same here, I’m puzzled. zeit now just has such an amazing dev experience, I’d love to use it with CLJS!

thheller16:01:15

no I mean why must this be built by them? why not upload the compiled js?

thheller16:01:42

going to take forever if if has to download java/clojure/maven deps etc

denik16:01:47

not sure. they pride themselves with extremely fast builds / deploys https://twitter.com/rauchg/status/1060587045515493376

denik16:01:10

might also be that analyzer deps are cached

thheller16:01:32

already hate that everything is expressed by filenames. gotta hate languages without proper namespacing

denik16:01:25

can’t have everything. the motive seems to be to cover as many langs as possible. the lowest common denominator of any popular lang is the file, so it makes sense. imho, it’s quite impressive, this is powered by 4 langs https://monorepo-v2.now.sh/

thheller16:01:58

so as far as I understand it each file is "deployed" indepedently

thheller16:01:04

so say you have 5 cljs namespaces

thheller16:01:12

that will trigger 5 different cljs builds

thheller16:01:19

which is complete waste of resources

denik16:01:57

it doesn’t look like it works that way

denik16:01:40

and the config determining how many builds a project has: https://github.com/zeit/now-examples/blob/master/nextjs-news/now.json#L6

thheller16:01:45

> A builder can retain an archive of up to 100mb of the filesystem at build time.

thheller16:01:12

thats not enough to store a JVM download?

denik16:01:58

¯\(ツ)/¯ how large are the deps for go / pythong / php?

denik16:01:37

these are supported and fast from a few demo’s I’ve seen

thheller16:01:17

guess those don't count towards the cache archive?

thheller16:01:28

no idea what is happening with any of this 😛

denik16:01:51

equally clueless here. however, I think getting clojurescript into now would be great. it’s similar to the deployment part of datomic cloud, just for cljs and other langs. Since now is very popular among hobbyists the exposure of cljs in their builders could also attract / lower the bar for beginners

denik16:01:18

now dev seems to offer a local build process (I think with file watcher?) as well

thheller16:01:55

well it is already trivial to run the code. building it is just tricky

thheller16:01:31

not sure what exactly it is building in the first place with just plan .js files for example

denik16:01:22

there might be a way to hack by compiling first and then building with the node and/or static builder

thheller16:01:18

yeah that is trivial

thheller17:01:57

alright this makes more sense now

thheller17:01:17

I guess it just needs one file to trigger everything but that file can be shadow-cljs.edn

thheller17:01:24

same as

{
  "version": 2,
  "builds": [
    { "src": "docs/package.json", "use": "@now/static-build" },
    { "src": "blog/package.json", "use": "@now/static-build" }
  ]
}

thheller17:01:47

alright I'm intrigued 😉

denik14:01:16

since shadow-cljs is an npm module, this should be very straightforward, right?

thheller14:01:49

the npm package is only a very thin layer to access the JVM stuff

denik14:01:36

does the npm package handle installing the java, clojure if it’s not there or does it expect it on the classpath

thheller14:01:49

it expects java to be installed yes

thheller17:01:58

@U050CJFRU I just did my first test now deployment. As expected it is trivial if you compile the code locally and just deploy the generated .js

thheller17:01:33

creating a custom builder would then just involve something that downloads the JVM and stuff. not sure thats worth the effort since debugging stuff is pretty annoying

thheller17:01:58

(ns demo.now)

(defn handler [^js req ^js res]
  (.end res "Hello World"))

thheller17:01:10

:now-lambda
  {:target :node-library
   :exports-var demo.now/handler
   :output-to "out/demo-now/index.js"}

thheller17:01:37

shadow-cljs release now-lambda cd out/demo-now now

thheller17:01:13

should probably extract that into a proper example. just wanted to get something running quickly and this does the trick

thheller17:01:48

to be honest the now builders currently just look like a super terrible CI implementation

denik01:01:17

thanks @thheller. Yes builders do look messy. Still when they work they work! Just want to write and deploy cljs quickly (and cheaply which lamdas are)

thheller10:01:11

right now "quickly" probably means compiling locally and deploying the compiled .js files directly. downloading java, maven deps, npm install on each build is probably way too slow when using a custom builder

thheller10:01:28

cache is also max 100mb which is nowhere near enough.

thheller10:01:48

the go builder also apparatently downloads go on each build and doesn't cache it

jntn12:01:18

I have set up a free travis build that builds and deploys a shadow-cljs project to now.

jntn12:01:36

Works like a charm 🙂

Whiskas20:01:42

how can i ensure i’m not running two versions of react at the same time?

Whiskas20:01:34

i am already using :exclusions [cljsjs/reac cljsjs/react-dom]

Whiskas20:01:42

and importing react from npm

lilactown20:01:10

in shadow-cljs, React won’t be loaded from cljsjs whether you exclude it or not

lilactown20:01:17

what’s your package.json look like?

lilactown20:01:23

and are you loading any other bundles on the webpage you’re running your CLJS code?

leocardoso20:01:14

Has anyone used shadow-cljs with single-spa?

thheller20:01:06

@mateus.pimentel.w shadow-cljs ensures that cljsjs is not used. so no need to worry about including it.

thosmos21:01:04

I'm coding two very different but related builds with different package.json files: one a :node-library running Google Cloud Functions, and one a browser app that communicates with those functions via Firebase. I'd also like to share some common code between them. Is there a way to specify different package.json files per build in one shadow-cljs and build these both from one shadow-cljs server run, or is it best to run two separate shadow-cljs instances?

thosmos21:01:57

Also, is there a way to run a watch on a node-library and prevent the repl and websockets stuff loading? It's causing errors in the local firebase cloud functions emulator. I'm only able to get release builds to work with it, and it'd be nice to just have the release build get triggered when the code changes, but otherwise have it be exactly the same code as a release build.

thheller21:01:36

@thosmos what I recommend doing is keeping a dedicated directory for your node builds/packages

thheller21:01:54

so each npm package gets its own directory with its own package.json

thheller21:01:13

and the CLJS isn't kept in that directory at all. the compiler output just goes there

thheller21:01:08

@leocardosoti oh. didn't realise that is a framework. no not aware of anyone using that

leocardoso21:01:20

i mean the single spa framework

thheller21:01:56

@thosmos what kind of issue do you get with the functions emulator? you can just disable the websockets stuff with :devtools {:enabled false} (like in the above config)

thosmos21:01:16

ah yes I just saw that in your example, but I missed it in the manual

thosmos21:01:14

The emulator error is

error: SHADOW import error /Users/thomas/Develop/take2/experiments/threshold-functions/functions/.shadow-cljs/builds/gcf/dev/out/cljs-runtime/shadow.js.shim.module$ws.js
...
Error: Cannot find module 'ws'

thheller21:01:52

npm install ws?

thosmos21:01:46

ah, now it's working with :devtools {:enabled false}

thosmos21:01:25

I'm still getting an error firebase > error: no "source-map-support" (run "npm install source-map-support --save-dev" to get it) but I think I remember a shadow config to disable source-maps

thosmos21:01:40

ok, :compilar-options {:source-map false} fixed that, so now it's working great! Wow, I'm so impressed with shadow-cljs Thank you!

thheller21:01:46

you may have more luck with :npm-module instead of :node-library if the emulator is so picky