Fork me on GitHub
#shadow-cljs
<
2019-12-16
>
cfleming04:12:37

I’m migrating my legacy cljsbuild app (for Cursive licensing) over to shadow. For the web part, I compile separate JS for separate pages, i.e. I have pages for buy, renew, quote etc. They share some code but currently I’m compiling them into separate JS. They all use the same output dir. I thought that in Shadow I’d be able to use modules within a single build for this, but when I try to configure this I get the error: “two modules without deps, please specify which one is the default”. I’m not sure what that means - should I be using separate builds for this?

superstructor05:12:51

Are you using :depends-on @cfleming?

superstructor05:12:12

E.g.

{...
 :output-dir "public/js"
 :modules
 {:shared
  {:entries [my.app.common]}
  :home
  {:entries [my.app.home]
   :depends-on #{:shared}}
  :login
  {:entries [my.app.login]
   :depends-on #{:shared}}
  :protected
  {:entries [my.app.protected]
   :depends-on #{:shared}}

cfleming06:12:34

No, but in this case none of my modules depend on one another. They’re essentially independent apps.

tianshu07:12:58

Modules are used for dynamic load in one app, different apps should have their own build. localhost:9630 is the default web console of shadow-cljs, you can use it to start/stop your builds.

cfleming08:12:27

Ok, thanks - I’ll separate them into different builds then.

thheller09:12:50

no. definitely use :modules

thheller09:12:06

but the difference to regular CLJS is that there is no default :cljs-base module.

cfleming09:12:32

Ok, what should I use for the default module, then?

thheller09:12:41

so as @U0G75S29H showed you need to declare one :shared module that all others depend on. you can use :entries []

cfleming09:12:57

Ah, ok, I’ll do that, thanks.

thheller09:12:59

that'll move all actually shared code there

cfleming09:12:50

So when I deploy a production build, will that load two JS files for each page? The shared and then the page-specific?

thheller09:12:53

in the pages then just load shared.js and the-page-you-are-on.js via HTML

cfleming09:12:00

Right, snap.

thheller09:12:09

no need to use the loader.

cfleming09:12:11

Ok, thanks, I’ll try that.

cfleming01:12:14

So this is what I ended up with:

:modules    {:shared      {:entries []}
             :pay         {:init-fn    site.pay/init!
                           :depends-on #{:shared}}
             :quote       {:init-fn    site.quote/init!
                           :depends-on #{:shared}}
             :buy         {:init-fn    site.buy/init!
                           :depends-on #{:shared}}
             :renew       {:init-fn    site.renew/init!
                           :depends-on #{:shared}}
However when I compile, I get the following:
[:site] Build failure:
Module Entry "site.buy" was moved out of module ":buy".
It was moved to ":shared" and used by #{:buy :quote}.

thheller09:12:14

this means that the site.buy ns was used somewhere in the :quote module. likely a direct (:require [site.quote ...])

thheller09:12:39

you can either make the buy module depend on quote

thheller09:12:54

or move the shared code into an extra ns so it can be moved out

thheller09:12:30

or just combine quote/buy into one

cfleming10:12:22

Ah, I see - I’ll play with that tomorrow, thanks.

cfleming10:12:54

It’s amazing how much shadow has removed the incidental complexity in my project, it’s very nice indeed.

👍 4
cfleming00:12:56

If I make my quote module depend on buy and shared, then I guess I need to load both in my HTML? i.e. I need shared.js, buy.js and quote.js in quote.html? Or is the shared code all moved out to shared.js?

cfleming00:12:44

I remember seeing in the doc that shared code is moved to the leaves as much as possible, is Shadow smart enough to see that shared is common to both buy and quote, and to put the code required by both there?

thheller00:12:05

no you need to load them all. the goal is to move code as close to the "edges" as possible. the goal is to keep shared as small as possible

cfleming00:12:26

Ah, I see - thanks.

cfleming00:12:51

Is the order of loading the modules in the HTML important? I know I have to load shared before quote, but is there a good way to know that I need (presumably) buy after shared but before quote?

thheller00:12:29

yes order is important. order is logical. all depends-on must be loaded before and that applies to all moduels being loaded

cfleming00:12:55

Yes, that makes sense, thanks.

cfleming07:12:04

If I understand the documentation correctly, if I have a :node-script build and I watch it, then hot code reloading should just work - is that correct? Is something logged somewhere when code is reloaded in that case?

thheller09:12:10

@cfleming did you specify the lifecycle hooks? either (defn ^:dev/after-load do-something-after-reload [] ...)?

Michaël Salihi11:12:50

A simple question about the syntax this hook (or hook in generally), this is exactly the same, right ? (defn ^:dev/after-load... vs (defn {:dev/after-load true}...

thheller13:12:48

well no. the map has to come after the name but the ^ comes before 😛

Michaël Salihi14:12:03

Haha Ok thx 🙂

thheller09:12:18

it should be logging something yes

cfleming09:12:41

I hadn’t specified a hook, no - I’ll try that tomorrow.

thheller09:12:09

in node hot-reload is often tricky because so much state is kept in some callbacks somewhere

cfleming09:12:39

Yeah, in this case it’s a node script running a web server and a local dynamo - I guess I’ll have to shut all that down, reload and then restart them.

thheller09:12:10

you just might be handing off a reference to some function that can't be hot reloaded

thheller09:12:50

so instead of passing some-fn it may help to pass #(some-fn %) instead

cfleming09:12:28

Great, thanks - I’ll go through that checklist tomorrow.

Aleed20:12:55

is it possible to run browser tests via terminal or is opening up browser required? and for node.js is there a way to have an automatic watching/running of tests similar to how browser tests run?

aisamu20:12:33

You can use the :karma target for cli tests (which has a "browser" runner as well IIRC)

👍 4