Fork me on GitHub
#shadow-cljs
<
2018-05-31
>
thheller06:05:12

@mhuebert try :web-worker true for the module but I think service workers should probably be their own build.

bupkis12:05:59

can the cljs-repl of shadow-cljs keep history, similar to the way lein does? (e.g. .lein-repl-history)

mhuebert12:05:30

@thheller sounds good. I was following the example and thought maybe there was a reason to keep it all in the same build, but separating it out makes it easy to change the output-dir without affecting the main build, which is better anyway.

thheller13:05:00

@mhuebert yeah I'm unsure about service workers. they are sort of standalone so making them part of a build is not ideal. including an extra cljs.core however makes it extra large which is also not ideal. just sticking with something like workbox.js might be an option though

mhuebert13:05:21

yeah, i was thinking of avoiding cljs altogether but didn’t find a library I liked yet, workbox.js looks good, thanks for the tip

thheller13:05:22

@samuel.wagen I have not done any work on that yet

bupkis14:05:17

no worries, was just wondering.

thheller14:05:46

open a ticket otherwise I'll just forget again. I only use the REPL from cursive and that keeps track of history and stuff

jmckitrick15:05:11

Is there a way to inject different env settings into a system based on dev vs release?

jmckitrick15:05:30

To clarify, I mean settings that I can use within my code, not just for the build itself?

jmckitrick15:05:18

Actually, I could have different source paths for each env, and pull in an ‘env’ namespace for each. Like Luminus sets up….

jmckitrick15:05:43

Or is there a better way?

jmckitrick15:05:43

You’re right! I read over that too quickly. Thanks!

jmckitrick15:05:02

I thought they were just for the compiler settings.

justinlee16:05:13

for people who use cursive and shadow, is there a way to automate the process of “select cljs repl and then issue the nrepl-select command”?

thheller16:05:37

do you mean the clj/cljs select box? that should switch automatically when you nrepl-select?

justinlee16:05:37

i’m being super lazy. i just want to avoid opening up the file that contains the nrepl-select magic and pasting into the repl

thheller16:05:32

I don't follow. what nrepl-select magic?

thheller16:05:38

you mean the actual command?

justinlee16:05:22

yea, in order to get to my app’s repl (which is the only repl I ever use) I cut-n-paste

(require '[shadow.cljs.devtools.api :as shadow])
(shadow/nrepl-select :app)
every time

thheller16:05:41

just call (shadow.cljs.devtools.api/nrepl-select :app) directly

thheller16:05:49

OR make a REPL command

thheller16:05:59

setup a keybinding for it

justinlee16:05:57

wait how do you make a repl command? i think that’s what I want. i’m trying to search for it but failing

justinlee16:05:33

oh sorry i’m an idiot. nevermind

justinlee16:05:50

oh i was overthinking this problem 🙂

thheller16:05:06

its a bit weird but the menu only shows up when actually connected to a REPL

thheller16:05:21

but then tools -> REPL -> add new command

thheller17:05:38

oh doh I just noticed. I didn't document a new thing 😛

thheller17:05:07

the REPL should now actually start out in shadow.user not user anymore

thheller17:05:18

so (shadow/nrepl-select :app) should work by default

thheller17:05:33

no need require anymore

thheller17:05:10

and you can set :repl {:init-ns something.foo} to make yours the default

thheller17:05:08

> You may also now put the :shadow/outputs config into the build config instead under the :outputs key since we don't need to namespace here.

thheller17:05:27

just edited that in 😉

wilkerlucio17:05:00

very nice 🙂

thheller19:05:54

------ ERROR -------------------------------------------------------------------
 File: C:\Users\thheller\code\shadow-cljs\src\dev\demo\es6.js:15:16
--------------------------------------------------------------------------------
  12 |   console.log("await value", value);
  13 | }
  14 | 
  15 | var obj = {hello-World: 1};
----------------------^---------------------------------------------------------
'}' expected
--------------------------------------------------------------------------------
  16 | 
  17 | export { foo, someAsyncFn };
  18 | export default "defaultExport";
--------------------------------------------------------------------------------

thheller19:05:21

those that use the .js support will soon get proper errors for those

thheller19:05:49

the errors closure produces are weird .. but still better than before

lilactown19:05:46

hey thheller, do you have any advice on how to go about scaffolding projects that are meant to be consumed as libraries?

lilactown19:05:53

I'm kind of struggling with deciding if I should put everything in project.clj and use lein integration, or if I should use shadow-cljs.edn and just put runtime deps in project.clj... plus there's also npm deps...

thheller19:05:57

yeah. unfortunately adding shadow-cljs deploy involves a lot of work so thats still ways off

thheller19:05:42

I think duplicate config is fine for now ... you don't update deps that often

thheller19:05:51

npm deps you can put in deps.cljs

thheller19:05:27

so in the setup above src/main/deps.cljs {:npm-deps {"react" "^16.3.0"}}

lilactown19:05:39

huh. is that a convention outside of shadow-cljs?

thheller19:05:08

well only shadow-cljs actively uses npm so its not well supported anywhere else

thheller19:05:24

but deps.cljs is officially supported by CLJS, I did not "invent" that

thheller19:05:13

at this point it is probably still safer for libs to use cljsjs

kurt-o-sys19:05:20

I'm having the react-flatpickr component and I'm trying to do this: https://flatpickr.js.org/plugins/#weekselect Everything else seems to work, but adding a plugin seems to fail... Here's some relevant code:

(ns ...
  (:require ...
            ["react-flatpickr" :default Flatpickr]
            ["flatpickr/dist/l10n/nl.js" :refer [Dutch]]
            ["flatpickr/dist/plugins/weekSelect/weekSelect" :default weekSelectPlugin]))


(defn week-picker [...]
  [...
    [:> Flatpickr {:options (clj->js {:locale      Dutch
                                      :defaultDate (coerce/to-date selected-calendar-date)
                                      :plugins     [(weekSelectPlugin. {})]
                                      :weekNumbers true})
                   :onChange    (fn [selected-dates _ _ ] (js/console.log "--" selected-dates))}]
  ...
I'm getting this error: Uncaught TypeError: module$node_modules$flatpickr$dist$plugins$weekSelect$weekSelect.default is not a constructor

kurt-o-sys19:05:50

I have the feeling I'm missing something... but I fail to see what 🙂. All other imports seem to work fine, but this plugin-thing doesn't work

thheller19:05:00

@kurt-o-sys unfortunately some packages include ES6 example but actually ship CommonJS

kurt-o-sys19:05:05

ok... which means they can't be imported?

thheller19:05:16

try this in the REPL (require '["flatpickr/dist/plugins/weekSelect/weekSelect" :as x]) then (js/console.log x)

thheller19:05:38

if that exported object has a .default property the :default will work

thheller19:05:47

otherwise it might just be :as ... instead of :default

kurt-o-sys19:05:04

ok, let me check 🙂

thheller19:05:04

they can be used fine but compatibility is weird

thheller20:05:51

otherwise you are calling (weekSelectPlugin. {}) maybe you are supposed to call (weekSelectPlugin {})?

thheller20:05:08

new Thing() vs Thing();

kurt-o-sys20:05:47

yeah, well... I'm trying to fin dout 🙂

thheller20:05:48

ah new is correct ... nvm

kurt-o-sys20:05:41

well, the js/console.log gives me:

ƒ (){return function(a){function b(b){var c=b.target;if(c.classList.contains("flatpickr-day")){b=a.days.childNodes;var d=c.$i/7;c=b[7*Math.floor(d)].dateObj;d=b[7*Math.ceil(d+.01)-1].dateObj;for(var h=…

thheller20:05:06

ok its just a function. then use :as weekSelectPlugin and that should work

thheller20:05:57

(weekSelectPlugin. #js {}) though as it won't understand CLJS maps

thheller20:05:21

[1:1]~cljs.user=> (require '["flatpickr/dist/plugins/weekSelect/weekSelect" :as x])
nil
[1:1]~cljs.user=> (x. #js {})
#object[Function]

👍 4
kurt-o-sys20:05:27

right. nice.

thheller20:05:28

seems to work

kurt-o-sys20:05:01

niiice! thx a lot!

kurt-o-sys20:05:18

another question @thheller: I'm having a https://github.com/Day8/re-frame app and when I start it using shadow-cljs watch app, hot reload doesn't seem to work as expected. I have a page with a menu, let's say page1 and page2. When I'm on page1, the content of page1 is shown, obviously. However, when I update that page (the content of page1), it is not updated in the browser. When I click in the menu page2 and page1 again, the update is there...

kurt-o-sys20:05:46

this is the config:

{:lein     true
 :jvm-opts ["--add-modules" "java.xml.bind"]
 :nrepl    {:port 3333}
 :builds   {:app {:target           :browser
                  :output-dir       "resources/public/js"
                  :asset-path       "/js"
                  :modules          {:main {:entries [ui-app.core]}}
                  :compiler-options {:closure-warnings {:global-this :off}
                                     :closure-defines  {"re_frame.trace.trace_enabled_QMARK_"        true
                                                        "day8.re_frame.tracing.trace_enabled_QMARK_" true}}
                  :devtools         {:http-root "resources/public"
                                     :http-port 3449
                                     :preloads  [shadow.cljs.devtools.client.hud
                                                 devtools.preload
                                                 day8.re-frame-10x.preload]}}}}

thheller20:05:29

@kurt-o-sys there is no :after-load callback. do you have one configured in the code? using ^:dev/after-load somewhere in the code?

thheller20:05:38

the update is not there since you need to trigger a re-render after the code was loaded somehow

thheller20:05:56

did you follow a template or so?

kurt-o-sys20:05:55

yeah, I had a template from somewhere... and no, I have no ^:dev/after-load anywhere 🙂. I'm still new to shadow-cljs 🙂

thheller20:05:18

well if you used figwheel before you'd have a :on-jsload callback in the config

thheller20:05:26

if you have a (defn render [] ...) in your ui-app.core just add (defn ^:dev/after-load render [] ..)

thheller20:05:09

or add :devtools {:after-load ui-app.core/render ...} to your config. same result.

kurt-o-sys20:05:40

ok, makes sense! will do.

kurt-o-sys21:05:07

well, I pass config to that render (which comes from the index.html), but that shouldn't be an issue, should it?

thheller21:05:42

I always recommend this setup

thheller21:05:26

you call init from the HTML. if you pass config into that method you add a (defonce config-ref (atom nil)) and then (reset! config-ref the-config) in init

thheller21:05:37

start then just derefs the config-ref

thheller21:05:45

and proceeds as usual

👍 4
kurt-o-sys21:05:25

not using atom now, but I already kept it in the re-frame app state (db). I'm just reading it from there. Thx a lot! Love shadow-cljs more and more.

👍 4
tony.kay21:05:59

anyone using shadow-cljs with react 16? I’m getting React not defined errors on release builds

mitchelkuijpers08:06:23

That is weird, it works for us. Maybe you could try deleting the .shadow-cljs folder and then do a clean npm install

tony.kay12:06:37

Yeah, I've tried all of that. A vanilla Fulcro template with React 16 is fine. Something weird is hosed.

tony.kay12:06:08

A git clean -xfd wipe doesn't help

mitchelkuijpers13:06:00

Have you double checked package.json so that it contains:

"react": "16.3.2",
    "react-dom": "16.3.2",

mitchelkuijpers13:06:40

I know I am asking dumb questions but I a am trying to get to the root cause

mitchelkuijpers13:06:55

You could also check package-lock.json which should get generated

mitchelkuijpers13:06:44

Do you have:

(ns cljsjs.react
  (:require ["react" :as react]))

(js/goog.exportSymbol "React" react)
Not sure if that is still necessary with the newest shadow-cljs

tony.kay13:06:52

I even tried manually coding in a set of global React at the entry point

tony.kay13:06:47

I didn't try it via an export...I'll try that. Why would Fulcro template work without that (and this one as well for months), and suddenly need it?

tony.kay13:06:23

if it were a new project, I'd suspect those kinds of things. With this one I suspect that some dependency loop or something in npm deps is confusing things.

tony.kay13:06:24

but I tried backing out the one I know was added recently and that didn't seem to help. The upgrade to React 16 was the other one...and it is wanting core-js at 1.x and something else wants 2.x, so not sure if that could hose things.

tony.kay13:06:43

such a long list of deps it is mind boggling

mitchelkuijpers13:06:08

Oh dear, which version of shadow are you using though? And are they the same in package.json and project.clj?

tony.kay13:06:18

Yeah, Fulcro issue

tony.kay13:06:26

thanks for the help 🙂

kwladyka22:05:36

(ns cm.core
  (:require [reagent.core :as reagent]
            [re-frame.core :as re-frame]
            [cm.events :as events]
            [cm.views :as views]
            [cm.config :as config]
            [bidi.bidi :as bidi]
            [goog.events :as goog-events]
            [goog.history.EventType :as EventType]

            [taoensso.timbre :as l])
  (:import goog.History))

(def route ["/" {"log-in" :log-in
                 "log-out" :log-out
                 "sign-up" :sign-up}])

(defmulti handler #(:handler %))

(defmethod handler :default [request]
  (l/info "page" request)
  (re-frame/dispatch [:handler (:handler request)]))

(defn hook-browser-navigation! []
  (doto (History.)
    (goog-events/listen
      EventType/NAVIGATE
      (fn [event]
        (->> (.-token event)
             (bidi/match-route route)
             (handler))))
    (.setEnabled true)))

(defn dev-setup []
  (when config/debug?
    (enable-console-print!)
    (println "dev mode")))

(defn ^:dev/after-load mount-root []
  (re-frame/clear-subscription-cache!)
  (reagent/render [views/page]
                  (.getElementById js/document "app"))
  (hook-browser-navigation!)) ;; <<<<<<<< this line

(defn ^:export init []
  (re-frame/dispatch-sync [::events/initialize-db])
  (dev-setup)
  (mount-root))
After reload page in web browser without any change of code (like add enter on the end of file) I get this HTML in page:
<html><head></head><body><input type="text" name="history_state1" id="history_state1" style="display:none"></body></html>
So I end with this error:
env.cljs:168 error when calling lifecycle function cm.core/mount-root Error: Target container is not a DOM element.
    at h.exports (invariant.js:43)
    at sa (react-dom.development.js:17117)
    at Object.render (react-dom.development.js:17196)
    at Object.reagent$dom$render_comp [as render_comp] (dom.cljs:20)
    at Function.reagent.dom.render.cljs$core$IFn$_invoke$arity$3 (dom.cljs:44)
    at Function.reagent.dom.render.cljs$core$IFn$_invoke$arity$2 (dom.cljs:39)
    at Function.reagent.core.render.cljs$core$IFn$_invoke$arity$2 (core.cljs:74)
    at cm$core$mount_root (core.cljs:51)
    at shadow.cljs.devtools.client.env.make_task_fn (env.cljs:165)
    at shadow$cljs$devtools$client$env$do_js_reload_STAR_ (env.cljs:173)
Why? How to fix it? What I want to achieve: URL navigation like url#/log-in. That is why I added (hook-browser-navigation!) but in some magic way it has conflict with shadow-cljs during development.