Fork me on GitHub
#shadow-cljs
<
2019-12-10
>
Aleed04:12:38

what's the clj/cljs way of linking a dependency so you can use the local version rather than remote one? I know I can reference a dependency by local path but is there a way to do it without changing code?

Shuai Lin07:12:30

One possible way is, in src/main of your project, create a symlink to the src directory of the local dep, e.g. src/main/foo where foo is a link to ~/dev/foo-project/src/foo

Shuai Lin07:12:38

Or if you use emacs, you can simply link a buffer of the local dep project to the cider session of your own project, so you can modify the source of the local dep project, and eval it in your repl

bbss14:12:01

another way if you use deps.edn is :local/root

{:paths ["src" "resources"]
 :deps {com.fulcrologic/fulcro {#_#_:mvn/version "3.0.3"
        ....                        :local/root "/Users/me/fulcro"}
        lilactown/hx {:mvn/version "0.5.3"}}}

👍 4
Aleed04:12:10

(the js equivalent would be yarn link)

conan15:12:56

Hi everybody, I'm trying to get css reloading working, but I just can't figure it out. I'm not using the built-in web server, my app contains a web server that serves static assets. I've set my :watch-dir to "resources/public", which is the root that the web server serves from; still no changes are ever pushed (i see them when i reload the page). My css lives at resources/public/css/compiled, and is linked in the HTML as <link rel="stylesheet" href="/css/compiled/cue.css?cache-buster=<cache-buster>" />. What am I doing wrong?

conan16:12:36

maybe there's something i need to run as part of the command i use to kick off shadow-cljs? at the moment i run npx shadow-cljs watch app

thheller17:12:24

it looks fine to me. maybe try without ?cache-buster? your webserver just may be caching to aggressively too and only serving the "old" content when another request is made?

thheller17:12:47

or maybe you configured something in the wrong place?

thheller17:12:53

kinda hard to tell without seeing your config

thheller17:12:45

it all looks correct from what you described

conan17:12:59

yeah i thought it might be the cache-buster but that doesn't make a difference

conan17:12:05

here's my config

{:lein {:profile "+dev"}
 :builds
 {:app {:target :browser
        :output-dir "resources/public/js/compiled/"
        :asset-path "/js/compiled"
        :compiler-options {:infer-externs :auto}
        :dev {:compiler-options {:closure-defines
                                 {"day8.re_frame.tracing.trace_enabled_QMARK_" true
                                  "re_frame.trace.trace_enabled_QMARK_" true}}
              :devtools {:preloads [day8.re-frame-10x.preload]
                         :after-load user/after-load
                         :watch-dir "resources/public"}
              :external-config {:devtools/config {:features-to-install :all}}
              :pretty-print true
              :print-input-delimiter true
              :source-map true}
        :release {:compiler-options {:closure-defines {goog.DEBUG false}
                                     :optimizations :advanced}}
        :main cue.core
        :modules {:cue {:entries [cue.core]}}}}}

conan17:12:48

sorry trying to make it more legible

thheller17:12:37

:external-config needs to be in :compiler-options otherwise it has no effect

thheller17:12:54

pretty-print and source-map default to true and would other also need to be in :compiler-options

conan17:12:02

oh cool thanks

thheller17:12:03

:main cue.core does nothing

thheller17:12:24

other than that it looks fine

conan17:12:09

yeah i don't think i've gone crazy here. ok could it be the way i run shadow, which is with this?

(require
  '[orchestra.spec.test :as stest]
  '[shadow.cljs.devtools.api :as api]
  '[shadow.cljs.devtools.server :as server])
(server/start!)
(api/watch :app)
(api/repl :app)
(stest/instrument)

conan17:12:32

do i need to run something else to kick off the file watcher?

thheller17:12:52

nope thats it

thheller17:12:26

did you check the browser console/devtools? does it try to request css?

thheller17:12:54

you can also set :log {:level :debug} in shadow-cljs.edn top level

thheller18:12:05

that will log a bunch of extra stuff, including changed css files it found

conan18:12:21

i'll try that. no, i'm seeing nothing about css in the console, i'm pretty sure it's not watching for changes

conan18:12:15

no, there's no output on css compilation

thheller18:12:44

it is independent and has nothing to do with CLJS compilation

conan18:12:03

yeah that makes sense, i wouldn't expect the two to be connected

conan18:12:10

although presumably there's some shared infra to push changes

thheller18:12:22

hmm nevermind I just checked. must have removed the log messages

thheller18:12:35

I don't get any either. css reload works though

conan18:12:42

am i right to have "resources/public" as the value for my :watch-dir when my css lives at resources/public/css/compiled?

conan18:12:59

and is served from /css/compiled/cue.css

thheller18:12:34

basically you take watch-dir and append the path of the css

thheller18:12:40

that should be the path in your filesystem

thheller18:12:30

so resources/public + /css/compiled/cue.css

conan18:12:35

yeah makes sense.

conan18:12:18

my css compilation occurs in WSL, but shadow-cljs is runnign in windows. it's all on a windows filesystem though. could there be a problem with watching files on a windows filesystem?

conan18:12:59

actually i can test that by editing, and no, that isn't the problem

conan18:12:51

well, thanks for your help. the only way forward i can see is to stop using my webserver and pass my handler to shadow-cljs and see if i can get that working. much appreciated as ever!

thheller18:12:57

the webserver isn't even involved in this so it should be working fine. I know its working for others too

thheller18:12:11

but you never answered my question about what the browser devtools show?

thheller18:12:38

I mean the request panel? does it do something?

thheller18:12:50

you can also check if the websocket is receiving messages

conan18:12:39

no, there are no requests

thheller18:12:40

should see messages like this one {:type :asset-watch, :updates #{"/css/foo.css"}}

conan18:12:47

oh yeah let me check that

conan18:12:27

no, i'm seeing only repl ping/pong

thheller18:12:30

other than that I don't really know. I'm on windows too so that shouldn't be an issue

conan18:12:48

same deal running from a terminal inside wsl, so it's something to do with my project and not my environment

conan18:12:02

oh. i read in the docs that :watch-dir was only needed for non-webserver setups, but your comment about the webserver not being involved makes me wonder whether i misunderstood?

thheller18:12:02

if you configure the built-in webserver it just implicitly also sets :watch-dir

thheller18:12:04

nothing else to it

thheller18:12:48

if you reproduce this in a simple project I can take a look

thheller18:12:25

it is working fine for me so kinda hard to guess what might be going on for you

conan18:12:43

yeah sure, ta

conan14:12:45

I've stripped it down and have a small repro https://github.com/conan/css-reload

conan14:12:20

same deal. tested using cursive and the command line, in windows, wsl and on mac. i'd be super grateful if you had time to cast an eye, but obviously only if you're curious.

thheller16:12:59

I rewrote the config to be

{:source-paths ["src/cljs"] 
 :dependencies
 [[reagent/reagent "0.8.1"]]
 :builds
 {:app {:target :browser
        :output-dir "resources/public/js/compiled/"
        :asset-path "/js/compiled"
        :compiler-options {:infer-externs :auto
                           :external-config {:devtools/config {:features-to-install :all}}}
        :devtools {:after-load user/after-load
                   :watch-dir "resources/public"}
        :modules {:css-reload {:entries [css-reload.core]}}}}}

thheller16:12:11

css reload works fine after doing that

thheller16:12:24

I have no clue why it doesn't work when running through lein

thheller16:12:58

I don't have time right now to figure out why ... there are many things wrong with the config though

thheller16:12:16

core.async version is too old

thheller16:12:33

cljs version is too old

thheller16:12:44

so I'm blaming some kind of dependency conflict on this

conan18:12:43

Amazing thanks!

Drew Verlee16:12:16

I'm trying to do some more code splitting on my project. I looked at the build report > main (default module> project files and picked a namespace that i dont believe needs to be loaded with the initial/default/main module. That is, i assume the namespace in question is shared by two modules which means its pushed into the default/main module. So if i make the shared namespace its own module then explicitly declear it a dep of the other ones, it wont be loaded with the main module: Before MainModule -> ns1 After MainModule -> XModule -> ZModule (ns1) YModule -> ZModule (ns1) I attempted to do just that, Then, when i try to build a report (or a build) I get an exception and then this message: Module Entry <Module Name> was moved out of module <Module Name> It was moved to <Module Name 2> and used by <some set of modules> I'm not sure what this is telling me. My intent was to create a new module (the <Module Name> from the msg above) so the message seems to be telling me that my it shouldnt create the new module because it was used by the other set of modules. Specifically, in that set of modules it lists the main module. Which from checking the dependencies isnt true. as in, main doesn't seem to depend on that module in any way.

thheller16:12:47

@drewverlee that error is telling you that an entry-ns (so either :entries or :init-fn) specified for one module was moved out

thheller16:12:18

the reasons for moving are most likely your :require setups somehow

Drew Verlee19:12:15

Thanks. So say i just have a small app with 3 namespaces: main, a, b. main requires a and b. So in shadow-cljs.end the setup would just be:

:modules 
{:main {:init-fn some.app.main/-main}
 :a {:entries [some.app.a} :depends-on #{:main}}
:b {:entries [some.app.a} :depends-on #{:main}}}
What would be an example of a something that would cause this error? Your implying something could be wrong with the requires? but i can't imagine what that could be. The app worked before the modules were added so in what scenario would it not work after modifying the shadow-cljs config to add modules.

thheller20:12:24

some.app.main cannot require some.app.a or b directly

thheller20:12:40

and some.app.a cannot require some.app.b directly

thheller20:12:46

neither can b require a

thheller20:12:50

thats pretty much it

Drew Verlee20:12:19

some.app.main cannot require some.app.a or b directly Concretely, you mean you cannot have: (ns some.app.main (:require [some.app.a :as a]) ? You have to use the lazy load functionality?

thheller16:12:26

also make sure you set :depends-on correctly

lilactown17:12:33

I have a JS file I’m including a CLJS lib that does this: import * as React from "react"; I tried to use import React from "react" at first, but I get an error when I execute the code from a REPL that React is undefined. Using the glob syntax fixed this. However, now a user has reported that trying to use it in React Native they receive this error:

--- helix/impl/class.js:1
Namespace imports (goog:some.Namespace) cannot use import * as. Did you mean to import React from 'goog:shadow.js.shim.module$react';?

thheller17:12:40

dunno what to do ...

lilactown17:12:08

is the ES6 code processed differently in browser vs RN?

thheller17:12:13

ESM-CJS interop sucks big time

lilactown17:12:49

I’m happy to do something hacky for now

thheller17:12:08

the issue is the ["react" :as react] is equiv of import * as react ...

thheller17:12:34

so changing it to make import React work would break the CLJS parts too

lilactown17:12:21

just to confirm though, import * as React should work in e.g. browsers right?

thheller17:12:28

and what makes things worse it that this is an "upcoming" default ... meaning that most libraries have not adopted this yet

lilactown17:12:55

it’s only when doing CJS interop w/ RN?

thheller17:12:55

so they would break too because they still expect import {createElement} from "react" or whatever to work

😭 4
thheller17:12:31

in the browser I can sort of control it better

thheller17:12:02

but RN builds the JS parts so I kinda can't do much

thheller17:12:25

or rather I dunno how to tell the closure compiler to "accept" this

lilactown17:12:29

so is it RN that is complaining about the glob syntax, or shadow-cljs, or closure?

thheller17:12:30

don't think its even possible

thheller17:12:54

closure complaining about what shadow-cljs gives it I guess

thheller17:12:10

I honestly don't know why it works one way but not the other

lilactown17:12:39

I wonder if it’s because I’m running it from a REPL

lilactown17:12:44

let me actually build some code with it

thheller17:12:00

you can use commonjs that is less problematic

thheller17:12:11

but .. no advanced for those parts anymore then

lilactown17:12:15

hmm yeah, it compiles fine in my browser build. at least in dev mode

lilactown17:12:06

this is ~34 lines of code so I don’t think missing out on advanced compilation will be a big deal

lilactown17:12:44

I also doubt it will be used super often, as it’s only used to construct a React class which is only necessary when using error boundaries

lilactown17:12:16

so as long as it doesn’t “infect” other code too much with it’s lack of optimizations I am fine with switching to CJS

thheller17:12:45

commonjs has other issues though ... it just sucks all around to be honest

thheller17:12:53

I don't like the situation but I don't know what to do

lilactown17:12:54

yeah 😞

thheller17:12:07

the way it works now has the "highest" compatibility with most packages

thheller17:12:15

if I change something like 50% of them break

thheller17:12:31

it'll be better when webpack v5 comes out and people adopt (since it will also break there)

lilactown17:12:39

well this seems to only be a problem when using npm packages inside of a JS file on the classpath

thheller17:12:51

but dunno how long that'll be and don't know what fun kind of changes the closure compiler throws into the mix until then

lilactown17:12:06

it’s a shit show for sure 😞

Aleed19:12:33

@U05224H0W can you maybe transpile it differently and output it to different file extensions, i.e. native.js versus web.js

Aleed19:12:41

so is the syntax that is meant to work is this import * as react so that you can do this ["react" :as react] but react native isn't recognizing that syntax since it transpiles the JS itself (yet it has to be this way in es6 for the cljs import statement to work)

Aleed19:12:48

did I understand that correctly?

Aleed19:12:47

tried to test this out in helix but doesn't look like shadow-cljs recognizes the different platform extensions. in either case, maybe that could be a solution since react native will look for .native.js before .js

thheller20:12:44

@lilactown actually what I'd suggest is not importing react at all in the .js file

thheller20:12:49

you are just exporting a function anyways

thheller20:12:58

so just pass Component as the first arg in the function

lilactown20:12:32

ah good idea

Drew Verlee19:12:07

Is there anything written about how shadow is doing the code splitting under the hood? I orginal through it was using webpack but i'm not sure and one of the tutorials implies its not.

Aleed19:12:54

@U05224H0W has an article on code splitting cljs, maybe it's what you're looking for https://code.thheller.com/blog/shadow-cljs/2019/03/03/code-splitting-clojurescript.html

Aleed19:12:21

(ah I see it was linked in thread, nvm)

lilactown19:12:47

it uses the google closure compiler

👍 4
Thomas Lisankie22:12:58

Hi all, I'm trying to use shadow-cljs in a project and it seems to be getting stuck when I try to "watch" my app. Here's what happens (<https://gist.github.com/TomLisankie/eb7cedb746fd18b53393ae7e197ee928>) when I run shadow-cljs watch app from within my project directory and here's the shadow-cljs.edn (<https://gist.github.com/TomLisankie/ed0c3ab4e83c14aaf0bdf48b18594d47>). I thought it was just taking a really long time to start or something, but then I tried the same command in a different shadow-cljs project and it was pretty quick. I'm guessing it's something wrong with my configuration, but I can't seem to figure out what. Any help would be much appreciated.

lilactown22:12:51

@thomas745 I don’t see anything wrong with that output

lilactown22:12:59

what are you expecting to happen vs. what is happening?

thheller22:12:02

@thomas745 shadow-cljs does not operate like figwheel. so if you are waiting for a REPL to show up that will never happen. instead you run shadow-cljs cljs-repl app separately to get your REPL when needed. the watch is independent of that

Thomas Lisankie22:12:03

@lilactown I'm expecting my app to show up when I go to the localhost URL provided like it does with figwheel but instead I just get a shadow-cljs dashboard with a list of active builds. It also has a listing for active HTTP servers but there aren't any running I'm guessing since none are being listed

lilactown22:12:01

ah, you need to configure a dev HTTP server I believe.

Thomas Lisankie22:12:00

@lilactown That works. Thanks a lot!