Fork me on GitHub
#shadow-cljs
<
2020-05-07
>
erwinrooijakkers08:05:11

Hi all, in shadow-cljs .edn if I depend on Reagent I have to use npm install [email protected] [email protected] create-react-class to install it’s dependencies, but they are mentioned in Reagent’s package.json. Same for npm packages that have dependencies in package.json, for some reason I have to add them manually. Is there a way to retrieve transitive dependencies automatically?

bitkiller.4208:05:40

Hi, i've a problem on hot reloading application on android device. My app is based on rn-rf-shadow (shadow-cljs, expo, reagent) https://github.com/PEZ/rn-rf-shadow . The hot reload has worked before. I think it has stopped as expo client updated react native and introduced fast-refresh. Fast-refresh is disabled on device. When I change my screen class the .cljs files are loaded and the start method is called.

load JS kickmanager/domain/start/start_screen.cljs
load JS kickmanager/domain/main/main_frame.cljs
call 
This is the start function
(defn start
  {:dev/after-load true}
  []
  (expo/render-root (r/as-element [PaperProvider {:theme custom-theme}
                                   [main-frame-with-socket]])))
Hope someone can give me a hint on what to investigate. Thx and regards.

thheller10:05:40

as far as shadow-cljs is concerned it did its job. why your client doesn't update I cannot say. after calling your start fn shadow-cljs is done and out of the picture

thheller10:05:55

maybe you have a component that decides to skip re-rendering somewhere

bitkiller.4210:05:10

Danke Thomas, I will re-check with clean projects and ivestigate further (Costs so much time on side-projects 🙂 ). I’ve already tried swapping reagent atoms on start … but no success so far.

bitkiller.4208:05:44

Works now. The fix was introducing the “dummy prop that always changes”, topic “Hooking up React” from the guide thheller mentioned above.

thheller08:05:09

@erwinrooijakkers the dependencies should be installed automatically when starting shadow-cljs? reagent doesn't have a package.json though so you just might be on a very old reagent version that doesn't declare its JS deps properly?

thheller08:05:39

well which version of reagent do you use?

erwinrooijakkers08:05:49

[reagent "1.0.0-alpha1"]

erwinrooijakkers08:05:59

But the version before that had same problem

erwinrooijakkers08:05:53

It’s this example project: https://github.com/transducer/zenroom-cljs-demo where I wanted to get Reagent + Zenroom (an npm package with a WASM file) to work

thheller08:05:30

that project has the dependencies listed in package.json?

erwinrooijakkers08:05:34

So I need to do this manually:

npm install [email protected] [email protected] create-react-class
npm install zenroom [email protected] regenerator-runtime

erwinrooijakkers08:05:40

Yes zenroom as well

thheller08:05:54

sorry I'm lost

thheller08:05:00

what is the problem?

thheller08:05:15

when dependencies are declared in package.json then shadow-cljs does nothing

thheller08:05:42

did you just miss the npm install (without any packages) to install the dependencies listed in package.json?

erwinrooijakkers08:05:38

I mean nmp install zenroom && npm install would work?

erwinrooijakkers08:05:05

I want these transitive dependencies to be added

erwinrooijakkers08:05:16

Without me doing it manually

thheller08:05:39

sorry I'm absolutely lost

thheller08:05:18

if you checkout that project and run npm install

thheller08:05:29

it will install all the packages listed in the package.json

thheller08:05:37

including all transitive dependencies

thheller08:05:00

I don't know why you are calling npm install zenroom since that will just install zenroom but not the rest

thheller08:05:14

but zenroom is listed in package.json so it will already be installed when you run npm install

erwinrooijakkers08:05:54

Yes I mean when you don’t have a package.json yet

erwinrooijakkers08:05:58

How you start from scratch

thheller08:05:03

you must have one

thheller08:05:10

npm init -y

erwinrooijakkers08:05:22

When I run npm init -y && npm install zenroom i do not have the transitive dependencies

thheller08:05:29

ok that is fine

erwinrooijakkers08:05:30

Then shadow-cljs complains

thheller08:05:58

complains how?

erwinrooijakkers08:05:31

And I have to manually run npm install [email protected] regenerator-runtime

erwinrooijakkers08:05:50

(Dependencies of zenroom)

erwinrooijakkers08:05:55

Maybe i just dont know how npm works

thheller08:05:30

if zenroom doesn't declare its dependencies properly then that has nothing to do with shadow-cljs?

thheller08:05:00

never ever look at at github repo when trying to figure out what a package does

thheller08:05:09

that is not the file that is being distributed with the package

thheller08:05:22

that is the actual file distributed with the package

erwinrooijakkers08:05:35

Okay that’s wrong…

erwinrooijakkers08:05:43

That version of core-js doesn’t work

erwinrooijakkers08:05:59

That’s the problem then

erwinrooijakkers08:05:03

And in relation to Reagent, is there a way to automatically install it’s npm dependencies (`npm install [email protected] [email protected] create-react-class`)?

thheller08:05:16

that happens on startup?

erwinrooijakkers08:05:27

I have Reagent added in shadow-cljs.edn

erwinrooijakkers08:05:46

Then i run shadow-cljs watch app

erwinrooijakkers08:05:03

Okay everything is cleared up

erwinrooijakkers08:05:14

The problem was not Reagent or shadow-cljs

erwinrooijakkers08:05:19

The problem was misconfigured zenroom package

erwinrooijakkers09:05:38

I added an issue on that package and they’ll look into it. I am happy that I understand now what went wrong and that shadow-cljs is doing everything as hoped.

erwinrooijakkers11:05:50

And @U05224H0W thanks a lot for thinking a long. I really appreciate the work your putting in shadow-cljs, it works supersmoothly, and also your active replies on people their problems here, like pinpointing my issue within a minute to be in the external package’s config.

Gordon King10:05:32

Hi has anyone has come across this error when doing a release.

The required namespace "shadow.js" is not available, it was required by "node_modules/react/index.js"
I don't have this anywhere in my code nor do I have any clue why react is requiring it. I can get the app to compile by installing the npm package shadow.js (whatever that is, plus a dependency rxjs) and it will compile successfully, but then when loading the compiled javascript I get the error
uncaught ReferenceError: shadow is not defined
Appreciate any hints or help.

thheller10:05:43

shadow.js is a helper namespace for npm JS interop. it comes with shadow-cljs. should be basically impossible that it doesn't exist?

thheller10:05:29

it is not an npm package, no clue how it even gets to that logic?

thheller10:05:52

do you use any kind of weird non-standard setup that may dynamically modify the classpath? ie. running in embedded? or boot maybe?

Gordon King11:05:09

Yes running via a boot task, sorry should have mentioned it works fine via the command line. That would be important to know. I've spent the evening trying to hunt down class path conflicts. Unfortunately prefer to keep it in boot as its a step in a complicated deployment rpm/generation process. Task based on https://github.com/jgdavey/boot-shadow-cljs/blob/master/src/com/joshuadavey/boot_shadow_cljs.clj

thheller11:05:31

don't know much about boot sorry. don't know how it even gets to a working state but then missing files that are in the exact same .jar

thheller11:05:57

but I'm currently rewriting a bunch of classpath logic so it might accidentally fix that issue as well

👍 4
Gordon King11:05:15

Someone had the same error doing something with Karma back in 2018...doesn't jog a memory just on the off chance? https://clojurians-log.clojureverse.org/shadow-cljs/2018-08-22

thheller11:05:56

thats not related

thheller11:05:13

uncaught ReferenceError: shadow is not defined is the effect of the file missing in the first place

thheller11:05:56

not sure how you ever get past the error of shadow.js missing but any attempt at hacking that together will make everything else fail

thheller11:05:01

the problem is the classpath issue

thheller11:05:48

this is downright scary old. certainly hope that is not the version you end up using.

thheller11:05:15

the entire boot thing is scary to be honest. I never understood how any of it works

Gordon King11:05:43

heh no I'm on your latest...

Gordon King11:05:49

Fixed it! Thanks for posting that above. it got me thinking that the install-dependencies hook might not be working or doing the right thing in the right order. I added shadow-cljs to the main boot dependencies and its working finally!

👍 4
Gordon King11:05:39

Its more magic than rails is boot...

Kevin12:05:20

Hi, does shadow-cljs have any method of handling (private) git repos as dependencies? Or should I just opt for deps.edn? I couldn’t really find anything on this topic.

Pavel Klavík12:05:55

Hi, I have the following code in my cljc file:

#?(:clj  (slurp (io/resource "my-web/test.txt"))
   :cljs (resource/inline "my-web/test.txt"))
Is there a way to replace it with a single macro so this is easier to use? Not sure how to distinguish between Shadow-cljs and Clojure running the macro?

thheller12:05:32

@kevin.van.rooijen not supported. need to use deps.edn for that.

Kevin12:05:46

All right, thanks! 🙂

thheller12:05:43

@pavel.klavik resource/inline should work from clojure too although that would mean you'd have shadow-cljs as a runtime dependency so probably not recommended for CLJ

Pavel Klavík12:05:00

Ok, I can test that, I don't really care about runtime dependency since this is a library for static web compilation: https://github.com/OrgPad-com/volcano.

Pavel Klavík12:05:30

seem to work great, thx

Pavel Klavík12:05:00

btw. if I have an inline JS function defined in my html file:

<script>function f { ... }</script>
how can I call it from my Clojurescript call? I tried js/f, but I get that it is undefined.

thheller12:05:09

should be fine. did you ensure that is defined before your own code tries to access it?

Pavel Klavík12:05:58

The script is defined above, and I have :on-click defined on the button div at the bottom.

Pavel Klavík12:05:26

[:div.button-filled #?(:clj  {:onclick "f();"}
                       :cljs {:on-click #(js/f)})
     "Odeslat"]

thheller12:05:50

yeah you can't do that from hiccup, that is rendered by react

thheller12:05:20

just use :on-click js/f

thheller12:05:34

nevermind that would be the same

thheller12:05:53

the CLJ version is the problem I suppose?

Pavel Klavík12:05:18

no, cljs. clj works fine

thheller13:05:02

I can't tell if that code actually runs when it is declared

thheller13:05:17

your script tag including the cljs code comes after this?

thheller13:05:34

otherwise js/f is just nil at the time it reaches that point

Pavel Klavík13:05:30

ya, I am producing a single hiccup for the entire page, so it contains both the script and the button

thheller13:05:14

that isn't what I asked

thheller13:05:22

what is the actual order in your HTML

thheller13:05:44

<script>function f() ...<script> MUST come before <script src="js/foo.js"> (your compiled CLJS output)

Pavel Klavík13:05:43

ya, it happens like that:

thheller13:05:52

or do you produce the script tag itself from hiccup also?

Pavel Klavík13:05:11

script tag for f is produced by hiccup also right now

thheller13:05:26

yeah that doesn't work. that just emits it as text and never evals it

thheller13:05:14

need to actually js/goog.global.eval it instead, can skip the script tag

Pavel Klavík13:05:36

ya, makes sense, so what would be the solution? Is it possible to add some reflection call to on-click? Or should I split this and include the script before?

thheller13:05:05

well why isn't this part of the CLJS build in the first place?

thheller13:05:50

I mean why is it added as a script tag?

thheller13:05:16

you just need to eval it in some way before trying to access it

Pavel Klavík13:05:35

ok, so if I have a bunch of script files whose list is defined in runtime, how can I eval them? Should I call js/goog.global.eval on them?

Pavel Klavík13:05:21

basically, in development I need to somehow eval them, in building static web, I just need to inline them

thheller13:05:29

yes when loading them from JS just eval the code

Pavel Klavík13:05:47

so what should I call for that?

thheller13:05:53

(js/goog.global.eval the-code)?

thheller13:05:35

just make sure you don't do it on every reagent render, that would be pointless

Pavel Klavík13:05:08

so how should I approach this to have hot code reloading?

Pavel Klavík13:05:22

I should put it into mount-root fn?

thheller13:05:59

if the code you are loading that way is safe to reload you can do that yes

thheller13:05:35

or just put it into the page directly? I assume you generate the base page from CLJ anyways?

Pavel Klavík13:05:32

hmm, ya, combination of these might work

Pavel Klavík13:05:17

things like static libraries (i.e., jQuery) can go into the page directly, and scripts you write and want to inline can be included using js/goog.global.eval. thx, will test this out

thheller13:05:20

I don't quite understand what you are doing or why this stuff isn't part of the regular build though

Pavel Klavík13:05:04

it is a static website generator, where development runs as SPA using Reagent and Shadow-cljs, so you get hot code reloading, and then you build static website files

thheller13:05:55

so there is no compiled CLJS code on the page once you are done?

Pavel Klavík13:05:57

I am trying to add some basic js support so you can have contact forms, etc., but nothing too big

thheller13:05:05

ok I expected there to be some CLJS at runtime regardless. mostly because I wouldn't want to write any JS I guess 😛

Pavel Klavík13:05:26

ya, I feel the same, but basically the goal is to just have a few lines of JS for needed stuff, nothing big, and we want to optimize the download time

Pavel Klavík13:05:53

basically the idea is that I want the similar comfort as with Reagent and Shadow-cljs, but for developing static web

thheller13:05:21

well the :advanced CLJS build is basically the same size of jquery so thats no argument 😛

Pavel Klavík13:05:15

ya, I think I will probably get rid of jQuery as well, plain JS should be enough, but adding small amout of CLJS when you need to do more complicated stuff makes sense

Pavel Klavík14:05:30

ok, it seems to work, thx

Filipe Silva14:05:10

heya all, I have a question if someone is around: is it possible to add configuration items to the default node-repl? In my specific case I'd like to add a :resolve in :js-options that would always be used in the node repl

thheller14:05:16

you can merge that stuff in when starting the node-repl from CLJ

thheller14:05:35

(shadow/node-repl {:config-merge [{:js-options {:resolve ...}}]})

Filipe Silva14:05:49

there's no way to put it in shadow-cljs.edn then I take it?

thheller14:05:11

well you can use :build-defaults or :target-defaults (not documented anywhere though)

thheller14:05:24

say you want ALL your builds to share the same resolve config

thheller14:05:54

:build-defaults {:js-options {:resolve ...}}

thheller14:05:19

:target-defaults {:node-script {:js-options ...}} would only apply to :node-script builds

Filipe Silva14:05:51

is that something that should be documented? I can add it to the docs

thheller14:05:00

probably 😛

Filipe Silva14:05:32

I guess the real question is not if it should be documented, is if you'd like to support it

thheller14:05:44

node-repl should probably be configurable elsewhere too though. feels like a bad idea to try to abuse the defaults for that 😛

Filipe Silva14:05:45

if it is part of the supported features, then it should be documented

thheller14:05:17

I added it since I thought it might be a good idea but never actually used it anywhere 😛

Filipe Silva14:05:45

I don't know how legitimate my case is really... we have a bunch of node and browser builds, and they share some code. In the shared code, there's an import to a JS library that only works in browser. We added a resolve to redirect that require to a local js file that contains a stub. I would like to be able to say "for all builds but the browser build, resolve this library to the stub". That seems to be something that build-defaults would do well.

Filipe Silva14:05:42

at some point we tried to do the opposite: require the stub, and resolve the stub to the real library in the browser app, but that didn't seem to work

Filipe Silva14:05:57

I didn't debug why though, maybe I was resolving it wrong or something

thheller14:05:29

well the config merge is rather basic so there really no way to remove a :resolve once its there

Andy Heywood14:05:40

Am I right in thinking (it certainly seems to be the case) that if I already have a shadow-cljs server running in another process, shadow-cljs watch :test will not autorun tests?

Andy Heywood14:05:58

ohhhh I’m an idiot sry, they’re run and the output is in the server terminal

thheller14:05:10

it does autorun the tests but the output goes to the server process currently

thheller14:05:21

I think there is an open issue about that somewhere 😛

Andy Heywood14:05:26

yeah not ideal, but easy enough to work around

Andy Heywood14:05:40

I assume it makes no difference if I just lean on the test watcher as the server, instead of starting one explicitly

thheller14:05:34

testing will be different soon anyways I hope. working on something that should improve the situation a bit.

Derek14:05:51

is it the kaocha integration?

thheller14:05:43

no. that is happening separately though.

Derek14:05:58

cool 🙂

Filipe Silva14:05:31

does the user guide have a repository where I could contribute that :build-defaults bit to?

Filipe Silva14:05:10

just to be clear about the semantics

Filipe Silva14:05:35

by this do you mean that config items cannot be removed, or cannot be overwritten?

Filipe Silva14:05:11

e.g. if I set a resolve on build-defaults can I overwrite it on my app config?

thheller14:05:19

override yes, remove no.

Filipe Silva14:05:13

does it go in toplevel config, or inside :builds?

thheller14:05:54

merge order is build-defaults -> target-defaults -> actual build config -> extra config merges

Kamuela14:05:29

Is there a quickstart guide for Node.js server-side with shadow?

thheller14:05:39

just create a :node-script build and go 🙂

Kamuela14:05:12

I'm a few steps behind that.

;; shadow-cljs configuration
{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

 :dependencies
 []

 :builds
 {:backend
  {:target :node-script
   :modules
   {:main {:init-fn acme.backend.core}
    :output-to "main.js"}}}}
Here's what I'm trying

thheller16:05:04

:modules does not apply to :node-script. just plain :main.

Kamuela15:05:36

Thank you! Got some play code up and running 🙂