Fork me on GitHub
#shadow-cljs
<
2019-11-06
>
Filipe Silva10:11:46

while using the jack-in functionality on calva, I noticed an inconsistency related to shadow-cljs start

Filipe Silva10:11:18

If I use shadow-cljs start followed by jacking in, nrepl and server information is never shown

$ yarn shadow-cljs start
yarn run v1.17.3
$ D:\work\learn-re-frame-course-files\cheffy\node_modules\.bin\shadow-cljs start
shadow-cljs - config: D:\work\learn-re-frame-course-files\cheffy\shadow-cljs.edn  cli version: 2.8.69  node: v10.16.0
shadow-cljs - server starting ..................................... ready!
Done in 10.14s.
> Executing task: C:\Program Files\nodejs\npx.cmd shadow-cljs -d cider/piggieback:0.4.1 -d cider/cider-nrepl:0.22.4 watch :app <

shadow-cljs - config: d:\work\learn-re-frame-course-files\cheffy\shadow-cljs.edn  cli version: 2.8.69  node: v10.16.0
shadow-cljs - connected to server
shadow-cljs - watching build :app
[:app] Configuring build.
[:app] Compiling ...
[:app] Build completed. (691 files, 690 compiled, 0 warnings, 46.46s)

Filipe Silva10:11:23

this stands in contrast with not using shadow-cljs start at all, which shows full server information

Filipe Silva10:11:37

> Executing task: C:\Program Files\nodejs\npx.cmd shadow-cljs -d cider/piggieback:0.4.1 -d cider/cider-nrepl:0.22.4 watch :app <

shadow-cljs - config: d:\work\learn-re-frame-course-files\cheffy\shadow-cljs.edn  cli version: 2.8.69  node: v10.16.0
shadow-cljs - updating dependencies
shadow-cljs - dependencies updated
shadow-cljs - HTTP server available at 
shadow-cljs - server version: 2.8.69 running at 
shadow-cljs - nREPL server started on port 3333
shadow-cljs - watching build :app
[:app] Configuring build.
[:app] Compiling ...
[:app] Build completed. (691 files, 1 compiled, 0 warnings, 9.60s)

pez10:11:44

Maybe shadow-cljs watch figures out that the server is running?

pez10:11:48

Please file an issue specifically about this on Calva. I might be able to figure something out…

👍 4
thheller10:11:23

@filipematossilva start runs the server in the background and exits. the output is still logged but to a logfile in the .shadow-cljs dir

thheller10:11:36

shadow-cljs server will start in the forground and not exit

thheller10:11:45

watch will use a running server if there is one, otherwise it'll become the server

Filipe Silva10:11:50

I didn't know about the .shadow-cljs/server.stdout.log (and .stderr.log) files

Filipe Silva10:11:56

indeed it is there

Filipe Silva11:11:18

now I think this is the cause: > Since the nrepl.port file is also created on server startup and Calva looks for files created in .shadow-cljs, I suppose it will never see the file being created and just wait for that.

thheller11:11:26

how this is kinda intended to work is that a server is either started or already running

thheller11:11:34

tools should only interact via the REPL

thheller11:11:47

it should never regex anything?

Filipe Silva11:11:38

I'm not sure what those regex are actually used for, but I imagine they parse the output of invoking the watch command

Filipe Silva11:11:50

because jack-in also runs that automatically

pez12:11:04

It’s a long story. But anyway, I think we can figure something out. Thanks for filing the issue!

David Pham12:11:08

I wondered if anyone got this error lately: I am using ^:dev-reload with shadow-cljs, so far so good, but I randomly get the following error whenever I update my app. (It happens with material-ui, so not sure it is something on reagent/shadow-cljs or material-ui)

component.cljs:338 Uncaught TypeError: Cannot read property 'call' of undefined
    at new transparency.components.drawer.drawer_react (component.cljs:338)
    at constructClassInstance (react-dom.development.js:14240)
    at updateClassComponent (react-dom.development.js:18351)
    at beginWork$1 (react-dom.development.js:20109)
    at HTMLUnknownElement.callCallback (react-dom.development.js:363)
    at Object.invokeGuardedCallbackImpl (react-dom.development.js:412)
    at invokeGuardedCallback (react-dom.development.js:467)
    at beginWork$$1 (react-dom.development.js:25731)
    at performUnitOfWork (react-dom.development.js:24639)
    at workLoopSync (react-dom.development.js:24615)
transparency.components.app_bar.app_bar_react	@	component.cljs:338
constructClassInstance	@	react-dom.development.js:14240
updateClassComponent	@	react-dom.development.js:18351
beginWork$1	@	react-dom.development.js:20109
callCallback	@	react-dom.development.js:363
invokeGuardedCallbackImpl	@	react-dom.development.js:412
invokeGuardedCallback	@	react-dom.development.js:467
beginWork$$1	@	react-dom.development.js:25731
performUnitOfWork	@	react-dom.development.js:24639
workLoopSync	@	react-dom.development.js:24615
performSyncWorkOnRoot	@	react-dom.development.js:24183
eval	@	react-dom.development.js:12239
exports.unstable_runWithPriority	@	scheduler.development.js:816
runWithPriority$2	@	react-dom.development.js:12189
flushSyncCallbackQueueImpl	@	react-dom.development.js:12234
flushSyncCallbackQueue	@	react-dom.development.js:12222
scheduleWork	@	react-dom.development.js:23602
updateContainerAtExpirationTime	@	react-dom.development.js:26946
updateContainer	@	react-dom.development.js:27076
legacyRenderSubtreeIntoContainer	@	react-dom.development.js:27680
render	@	react-dom.development.js:27757
reagent$dom$render_comp	@	dom.cljs:19
eval	@	dom.cljs:43
eval	@	dom.cljs:38
eval	@	core.cljs:77
transparency$core$mount_app	@	core.cljs:21
eval	@	VM47974:1
shadow$cljs$devtools$client$browser$global_eval	@	browser.cljs:233
eval	@	browser.cljs:236
shadow$cljs$devtools$client$env$repl_call	@	env.cljs:106
shadow$cljs$devtools$client$browser$repl_invoke	@	browser.cljs:236
shadow$cljs$devtools$client$browser$handle_message	@	browser.cljs:288
eval	@	env.cljs:185
shadow$cljs$devtools$client$env$process_next_BANG_	@	env.cljs:173
shadow$cljs$devtools$client$env$process_ws_msg	@	env.cljs:186
eval	@	browser.cljs:368

thheller12:11:05

component.cljs:338 Uncaught TypeError: Cannot read property 'call' of undefined
    at new transparency.components.drawer.drawer_react (component.cljs:338)

thheller12:11:15

(something 1 2 3) when something is nil

David Pham12:11:29

The faulty code is this one: in reagent.impl.component

David Pham12:11:46

(defn create-class
  "Creates JS class based on provided Clojure map.

  Map keys should use `React.Component` method names (),
  and can be provided in snake-case or camelCase.
  Constructor function is defined using key `:getInitialState`.

  React built-in static methods or properties are automatically defined as statics."
  [body]
  {:pre [(map? body)]}
  (let [body (cljsify body)
        methods (map-to-js (apply dissoc body :displayName :getInitialState :constructor
                                  :render :reagentRender
                                  built-in-static-method-names))
        static-methods (map-to-js (select-keys body built-in-static-method-names))
        display-name (:displayName body)
        get-initial-state (:getInitialState body)
        construct (:constructor body)
        cmp (fn [props context updater]
              (this-as this
                (.call react/Component this props context updater) <<<<------------------------ THIS LINE
                (when construct
                  (construct this props))
                (when get-initial-state
                  (set! (.-state this) (get-initial-state this)))
                this))]

David Pham12:11:18

So react/Component would be nil?

thheller12:11:04

appears to be yes

David Pham12:11:36

I am using the npm version of react.

thheller12:11:52

at new transparency.components.drawer.drawer_react (component.cljs:338)

thheller12:11:04

the code you just posted?

David Pham12:11:12

So, I should just go inside reagent and change the requirement [react :as react] as ["react" :as react]

thheller12:11:26

no, that doesn't matter

thheller12:11:41

don't know why you bring up reagent though?

David Pham12:11:04

Because the call from the undefined comes from reagent

David Pham12:11:18

at new transparency.components.drawer.drawer_react (component.cljs:338) is called from reagent

thheller12:11:47

sorry I don't follow. that is not a regent namespace

David Pham12:11:24

component.cljs:338 is a reagent namespace

David Pham12:11:28

reagent.impl.component.cljs

thheller12:11:59

transparency.components.drawer.drawer_react this part is what I'm asking about

David Pham12:11:03

this is not a part of react/reagent.

David Pham12:11:08

but, whenever I ask chrome to debug on exception, it shows me reagent.impl.component namespace

thheller12:11:44

yes ... but it helps to know what transparency.components.drawer.drawer_react is

David Pham12:11:58

(defn drawer-react
  "The main components of the drawer. Refactor this tab to provides the tabs as
  argument."
  [{:keys [classes tabsPublic]}]
  (let [tabs-public tabsPublic
        tabs [[tabs-public (or @(subscribe [::drawer-displayed-sublists]) #{})]]]
    [:> mui-drawer
     {:open true
      :variant :persistent
      :class (cs (.-drawerPaper classes))
      :ModalProps #js {:onBackdropClick #(dispatch [:close-drawer])}
      :PaperProps #js {:class (cs (gobj/get classes "drawerPaperPaperProps"))}}
     [:div {:style {:width drawer-width}}
      [:div {:class (.-toolbarIcon classes)}
       [:> mui-icon-button {:onClick #(dispatch [:toggle-drawer])}
        [:> ic-chevron-left {:style {:color "white"}}]]]
      [list-divider classes]
      [:> mui-list {:style {:padding-top 0}}
       (into [:div] tabs)]]]))

thheller12:11:52

hmm yeah dunno 😛

thheller12:11:11

are you maybe messing with js/React in some way?

David Pham12:11:42

not defined though

David Pham12:11:52

when I write it in the repl

David Pham12:11:26

what is weird, is that it only appears wheneever I reload the code

David Pham12:11:56

maybe it is in the "updater" because it is undefined

thheller12:11:56

and when you debug react/Component is undefined?

thheller12:11:18

there should be a global of some kind module$node_modules$react$...

David Pham12:11:57

that is defined

thheller13:11:26

but that is what react/Component should be accessing?

David Pham13:11:52

hum... I don't know. I might try to dig a bit deeper, maybe this is the answer. My issue is the bug is random

David Pham13:11:37

only at reload

thheller13:11:43

it looks like you are calling transparency$core$mount_app from the REPL?

David Pham13:11:22

I rely on ^dev:after-load to reload the app

David Pham13:11:37

(defn ^:dev/after-load start []
  (rf/clear-subscription-cache!)
  (mount-app))

David Pham13:11:48

maybe I should not clear subscription cache xD

David Pham13:11:04

I should clear?

David Pham13:11:09

or should not?

thheller13:11:20

yes, clear. otherwise the UI won't update.

David Pham13:11:36

ok, I will try to come back when I can pinpoint the issue. But it is an annoying bug as it completely mess up with hot reloading.

thheller13:11:41

shadow$cljs$devtools$client$env$repl_call    @    env.cljs:106
shadow$cljs$devtools$client$browser$repl_invoke    @    browser.cljs:236
shadow$cljs$devtools$client$browser$handle_message    @    browser.cljs:288

thheller13:11:55

this part I can't explain. that is not called as part of a normal reload cycle.

David Pham13:11:22

Hum... Ok I will try to see. I am trying to use your new inspect feature as well

David Pham13:11:24

if that can help

thheller13:11:53

hmm no that runs separately and doesn't call that stuff either

thheller13:11:27

is your editor maybe sending stuff over the REPL?

David Pham13:11:43

I am using emacs

David Pham13:11:48

with shadow-cljs

David Pham13:11:06

I execute shadow-cljs watch app

David Pham13:11:10

and connect with cider-connect-cljs

thheller13:11:14

that does send a bunch of stuff all the time

thheller13:11:53

but not sure how it would affect the reload cycle

David Pham13:11:56

Got call, maybe this is the reason. I will check.

David Pham13:11:27

Did anyone got ReferenceError: $jscomp is not defined with google closure compiler?

David Pham14:11:36

I got it, just had to output es6 in the clojure compiler

Flo14:11:31

Trying to create a prod deployment from shadow-cljs + compojure project: starting from a completely blank skeleton via lein new re-frame foo +10x +re-frisk +handler and then run a lein with-profile prod uberjar I get this error:

[:app] Build completed. (95 files, 46 compiled, 0 warnings, 29.20s)
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
any ideas?

Flo14:11:45

kept the :uberjar target in project.clj as is, i.e.:

:uberjar {:source-paths ["env/prod/clj"]
               :dependencies [[day8.re-frame/tracing-stubs "0.5.3"]]
               :omit-source  true
               :main         foo.server
               :aot          [foo.server] 
               :uberjar-name "foo.jar"
               :prep-tasks   ["compile" ["prod"]]} 

hlolli15:11:22

@web20 do you have (defn -main [] ...) in foo.server, and (:gen-class) in it's namespace decleration?

hlolli15:11:37

this isn't a shadow-cljs problem, but looking at the source path, are you sure that ./env/prod/clj/foo/server.clj exists at this location?

hlolli15:11:56

also, I would do :aot :all to be safe

Flo15:11:02

@hlolli ha! no that's empty.. I assume lein prod would populate that path? even if I run lein prod (which runs -m shadow.cljs.devtools.cli release app), then env/prod/clj remains empty.

hlolli15:11:40

I would segment the the dubug process. 1. make sure that shadow-cljs is producing .js files from .cljs sources. And then, debug the server. Source paths here in this case are left untouced, only your target directory and uberjar are written during compilation.

Flo21:11:45

@hlolli fwiw, the issue was the following: The "prod" task contains an initial lein clean. So right after the "compile" :prep-task finished, it cleans its results, and then, naturally, the class cannot be found. Thanks for taking the time to take a look!