Fork me on GitHub
#clojurescript
<
2019-01-08
>
Kelly Innes00:01:57

Cool, that worked. Can the index.html file be set to make use of the manifest.edn mapping to get the correct bundle? Or is it meant to be set manually?

Kelly Innes00:01:45

Seems like the idea is to have the build step parse and replace

Kelly Innes01:01:42

Ended up writing this hacky thing to run as a lein alias after building the bundles:

Kelly Innes01:01:46

(ns build.add-hash
 (:gen-class))

(def index-path "./public/index.html")
(def two-hundred-path "./public/200.html")
(def manifest-path "./public/js/manifest.edn")
(def app-js-path "public/js/app.js")
(def app-js-file-to-replace "js/app.js")
(def replacement-regex
  (java.util.regex.Pattern/compile app-js-file-to-replace))

(defn -main
  "Add hash from the latest package bundle to the html files"
  [& args]
  (let [manifest (read-string (slurp manifest-path))
        hashed-filename (subs (get manifest app-js-path) 7)

        index-file (slurp index-path)
        adjusted-index (clojure.string/replace index-file
                                               replacement-regex
                                               hashed-filename)]
    (do
      (spit index-path adjusted-index)
      (spit two-hundred-path adjusted-index))))

lilactown05:01:09

has anyone done used websockets with CLJS on Node.js?

lilactown06:01:51

by which I mean, created a websocket server

chrisps06:01:44

How do I attack this problem:

chrisps06:01:55

clj -A:fig  -J-Xmx6g
[Figwheel] Validating figwheel-main.edn
[Figwheel] figwheel-main.edn is valid \(ツ)/
[Figwheel] Compiling build dev to "../priv/static/js/public/cljs-out/dev-main.js"
[Figwheel] Failed to compile build dev in 2.414 seconds.
[Figwheel] java.lang.StackOverflowError
          clojure.lang.PersistentVector/seq at PersistentVector.java(285)
                    clojure.lang.RT/seqFrom at RT.java(539)
                        clojure.lang.RT/seq at RT.java(533)
        clojure.core$seq__5387/invokeStatic at core.clj(137)

chrisps07:01:07

oh man, the reader was just confused over some garbled text in one of the sourcefiles :-0

chrisps08:01:24

why is everything so much nicer with figwheel?

lilactown08:01:35

another question: is there a way to conditionally require a namespace in CLJS? e.g. I want to detect if Datafiable exists before I require clojure.datafy

john16:01:58

While it is possible to check whether a particular var has been loaded from a namespace using tagged literals, the problem is that if your library is required before the other library is required, then it won't detect it. So the problem is, how can you ensure users downstream will load deps in your preferred order?

flyboarder17:01:35

perhaps conditional loading is the issue? why not have a namespace that loads deps in the correct order

flyboarder17:01:27

like use my-lib.datafy when you have datafy

lilactown17:01:48

I’m not sure I follow

lilactown17:01:05

what happens if the user doesn’t have datafy?

flyboarder17:01:15

then they dont include your namespace

lilactown17:01:17

my library needs to call clojure.datafy/nav etc.

flyboarder17:01:37

right so you have a direct dependency on datafy then

flyboarder17:01:57

then you should be including it as your own dependency

lilactown17:01:31

it’s provided by the clojure(script) core library

lilactown17:01:39

it’s just not in the clojure.core namespace

flyboarder17:01:13

sp why not require clojure.datafy?

lilactown17:01:13

I’d like my library to support versions of CLJS that don’t have datafy yet with a fallback

lilactown17:01:31

e.g. try to require clojure.datafy in the current version of CLJS 🙂 my library will not work. I don’t know how often people upgrade their CLJS version

flyboarder17:01:56

using datafy means you would require the latest version

flyboarder17:01:02

i.e. it wont be cross-version compatible, the best thing to do would be to keep all of the datafy code in a single optional namespace that your library consumer could use if they are also on the latest version

lilactown17:01:10

so it seems. my question was if there was some way to avoid that, doesn’t seem so

flyboarder17:01:49

sure you can, but you run the risk of the library-consumer building with an incompatible version of cljs

flyboarder17:01:05

the thing about using datafy is that it’s not like spec where it’s a separate lib its actually a language feature

flyboarder17:01:50

the thing to do in this case would be to run 2 versions of your library that build to different language versions

lilactown17:01:56

yeah. my library is already split into a set of adapters that can be installed depending on the platform you’re targeting (browser, node, JVM)

lilactown17:01:52

maybe I could split this up further. starts to feel kind of a lot if I have e.g. adapter-web and adapter-web-datafy, for each platform

john18:01:04

oh yeah... clojure.datafy will always be loaded before library namespaces, so the tagged-literals hack will work for you

lilactown18:01:46

what’s the tagged literals hack?

john18:01:27

Basically, tagged literals run at compile time, like macros, but even before macro expansion, so you can slip them into namespace declarations without breaking their specs

lilactown18:01:17

I still don’t understand how I would do it

lilactown18:01:38

AFAICT custom tagged literals are a PITA to setup in CLJS anyway. I tried it before and couldn’t get it to work

john18:01:20

yeah, it's sorta non-trivial

john18:01:23

is there a way, on the clojure-side, to detect if an ns is requirable, without causing a compile error when it's not requirable?

john19:01:40

If not, then maybe the hack won't work :thinking_face:

john19:01:48

Well, you could use *clojure-version*

john19:01:35

So like, in some clojure file my/readers.clj put:

(defn new? [[then? else?]]
  (let [v *clojure-version*
        new-enough? (and (<= 1 (:major v)) (<= 10 (:minor v)))]
    (if new-enough?
      then?
      else?)))
Then, in data_readers.cljc, add this to your map: my/new? my.readers/new?

lilactown19:01:07

but I need to detect if the clojurescript version is correct, not the clojure version

john19:01:08

Then you can do:

cljs.user=> #my/new? [1 2]
1

john19:01:59

hmmm. If you're using a newer version of CLJS that includes datafy, will the clojure version not be recent enough to have datafy? Not sure

lilactown19:01:21

sure. CLJS doesn't care what version of Clojure you have

lilactown19:01:46

and vice versa. I can be on Clojure 1.10 right now, but currently there is no version of CLJS that has datafy 😄

john19:01:42

hmm, yeah, even on the latest cljs (git sha, with datafy), if your deps have clojure 1.9, then datafy will be available in cljs but tagged literals will run in an environment with clojure 1.9

john19:01:00

Okay, I think I figured it out (I'm interested in if this can work too)

john19:01:54

This might work:

(defn datafy-exists? [[then? else?]]
  (let [opts (-> env/*compiler* deref :cljs.analyzer/constant-table
                 keys (->> (filter #{'clojure.datafy})))]
    (if opts
      then?
      else?)))

john19:01:59

Then in your tagged_literal.cljc file: my/datafy-exists? my.readers/datafy-exists?

john19:01:19

Then cljs.user=> #my/datafy-exists? [1 2] => 1

john19:01:18

Then, in your my/core.cljs clojurescript file, do:

(ns my.core
  #my/datafy-exists?
   [(:require [clojure.datafy :as d]
              [cljs.pprint :as pp])
    (:require [cljs.pprint :as pp])])

lilactown19:01:40

wow hah 😄

john19:01:03

🙂 Lemme know if that pans out for ya

lilactown19:01:05

I'll have to see if I can get this to work. last time I tried, I coulnd't get tagged_literal.cljc to be picked up by shadow-cljs

john19:01:28

I tested it all on vanilla cljs.main

john20:01:12

@lilactown Actually, this works better:

(defn exists? [[extant then? else?]]
  (if (-> env/*compiler* deref :cljs.analyzer/constant-table
        keys str (clojure.string/split #" ") vec (->> (some #{(str extant)})))
    then?
    else?))

john20:01:38

Then you do: cljs.user=> #my/exists? [clojure.core.protocols/datafy 1 2] => 1

john20:01:21

finicky stuff with evaluation at tagged_literal compile time

john21:01:46

oh, btw, you could also use this hack to get around having to use split code bases for node/browser/jvm, which I'm pretty sure you can detect through various means at compile time

lilactown08:01:00

@chris.schreiner because refreshing is for the birds!

thheller10:01:10

@lilactown that is possible only in clojure, not CLJS

kwladyka12:01:08

@lilactown but you can set manually by :closure-defines if you want to load this ns or not. It is what is happening during compilation

mfikes13:01:03

I'm not aware of a way to use :closure-defines to affect whether a particular namespace is required in an ns form.

Ac1dR3d12:01:18

hi everyone. can i ask, how you use CSSTransition?

orestis14:01:56

[:> TransitionGroup
        {:component "div"
         :class "list tags collection-view tags-list"
         } 
        (for [tag (state/tags-list state)]
          ^{:key (:id tag)}
          [:> CSSTransition
           {:timeout {:enter 250
                      :exit 150}
            :classNames "tag"}
           [tag-row tag
            (get-in state [:ui/tags (:id tag)])
            (:ui/select-all? state)]])]

orestis14:01:14

I need to run, but I got this working — here’s an example that works.

orestis14:01:39

And the style that goes with it:

[:style
      ".tag-enter { background-color: transparent;}"
      ".tag-enter.tag-enter-active { transition: background-color 250ms ease-out; background-color: #FFFF9B;}"
      ".tag-enter-done { transition: background-color 150ms ease-in; }"
      ".tag-exit { opacity: 0.7; max-height: 200px;}"
      ".tag-exit.tag-exit-active { opacity: 0.01; transition: all 150ms ease-out; max-height: 0px;}"
      ]

orestis14:01:06

Two things — a) you have to wrap things into a TransitionGroup b) you have to give explicit timeouts that match your animations.

orestis14:01:41

I’m using the “community” react-transition-group library, not react-with-addons-whatever. The components themselves have no idea about the animations.

orestis14:01:26

This is only for the case where React will animate deletions/additions to the DOM, I haven’t tried yet anything else.

Ac1dR3d12:01:47

i have tried importing new react-transition-group and using [:> CSSTransition

Ac1dR3d12:01:19

with classNames option but it seems it does not add class-names at all

Ac1dR3d12:01:26

on component change…

Ac1dR3d12:01:51

guess im not the only one stuck in this situation

Matt Butler13:01:05

Is there somewhere I should start when trying to speed up cljs compilation? I enabled compiler-stats but that only gives me 2 compile sources outputs. Is there a more verbose output or some other way to gain insight into what it's spending it's time on? Apologies for lack of code/output examples lmk if these are relevant :)

dnolen14:01:01

@mbutler there's really not so many ways to speed up compilation

dnolen14:01:18

:parallel-build true and if you were careful with your dependencies :aot-cache true

dnolen14:01:27

the latter will cause problems if you didn't audit everything

dnolen14:01:45

to see where time is being spent

dnolen14:01:49

:compiler-stats true

mfikes14:01:58

Another way that seemed to work in the past was to fix the JVM heap size, and not let it float

dnolen14:01:05

ah that's true

dnolen14:01:20

if your heap limit is too small the VM will spend most of it's time in GC

Matt Butler14:01:35

Ive just enabled parallel builds and knocked off a few seconds, i have compiler stats enabled but I only get

Compile sources, elapsed time: 1921.07242 msecs

Compile sources, elapsed time: 1821.224109 msecs

[Figwheel] Successfully compiled build app to "resources/public/cljs/main.js" in 17.82 seconds.

Matt Butler14:01:09

It would appear it's spending a lot of time doing something else based on this output but I don't know if I'm reading it right.

dnolen14:01:30

that looks like you're using an optimization setting to me (if there's that big of a gap)

Matt Butler14:01:34

Sorry for taking a while to post the output had to get it onto my phone :D

dnolen14:01:37

which you don't want to do in dev

Matt Butler14:01:22

Based on my reading of the config it should be optimisations :none, can you query the running app to check?

Matt Butler14:01:08

Some repl fn or something, thanks for the help before I forget.

Matt Butler14:01:48

Found the verbose compiler option, going to give that a go 🙂

dnolen14:01:30

@mbutler ah yeah sorry, :verbose + :compiler-stats will give you more info

👍 5
Matt Butler14:01:51

In the verbose output in what appears to be the compiler option map I have ups-foreign-libs with quite a lot of entries. I can't seem to find what that key indicates or if having a lot of entries in there is a problem :)

abdullahibra15:01:14

how can i debug these errors:

abdullahibra15:01:15

TypeError: b.Vh is not a function

abdullahibra15:01:52

it's working fine in dev mode but not working in min mode

abdullahibra15:01:12

how can i start fixing this?

dnolen15:01:25

@mbutler foreign libraries don't go through Closure so I don't see how that could be contributing to your compile time

dnolen15:01:55

@abdullahibra add the following to your compiler options :pretty-print true :pseudo-names true

dnolen15:01:06

it appears you are missing externs for the braintree stuff

Matt Butler16:01:37

Most of the pause/time (about 10s) is taken up before it outputs Compile sources, elapsed time: 1921.07242 msecs Does anyone know what kinds of things it (in this case figwheel main) is doing before that? Maybe give me an idea where to look :)

thheller16:01:00

@mbutler which version are you on? it might be indexing node_modules which can take quite a while.

Matt Butler16:01:48

@thheller 0.1.9. After I save I immediately get the "options passed to cljs compiler" output followed by nothing for 10 secs then some compiler output.

thheller16:01:02

CLJS version I mean

Matt Butler16:01:25

Oh whoops 1.10.339

thheller16:01:49

try 439. can't remember which version turned off that scan

Matt Butler16:01:35

Okay will do, thanks 🙂

john16:01:58

While it is possible to check whether a particular var has been loaded from a namespace using tagged literals, the problem is that if your library is required before the other library is required, then it won't detect it. So the problem is, how can you ensure users downstream will load deps in your preferred order?

lilactown17:01:41

how often do people upgrade their version of CLJS in a project they’re maintaining?

flyboarder17:01:11

I upgrade when my cljs compiler does

flyboarder17:01:20

currently using shadow-cljs

jstaab19:01:42

Hey everyone, I'm having some trouble with clojurescript's stack traces omitting some frames that seem like they ought to be included. Details in thread

jstaab19:01:59

Below is my stack trace:

at cljs.core.MapEntry.cljs$core$IIndexed$_nth$arity$2 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:6621:5)
at cljs.core.MapEntry.cljs$core$IFn$_invoke$arity$1 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:6570:1)
at Function.<anonymous> (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/my-project/policy/pos.cljs:115:3)
at Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$3 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:3866:8)
at Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$2 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:3861:6)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:3896:6)
at G__11950__delegate (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/my-project/utils/core.cljs:12:5)
at Function.my-project.utils.core.tracefn.G__11950.cljs$lang$applyTo (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/my-project/utils/core.cljs:11:10)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (/my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/cljs/core.cljs:3895:10)
at /my-project/.shadow-cljs/builds/test/dev/out/cljs-runtime/my-project/utils/core.cljs:169:48
As you can see, my project only shows up 4 times, though really only the top frame is relevant, since the bottom three are wrappers I've created around functions. However, this was several frames away from where nth was called, so I replaced a bunch of my defns with deftraced as defined below (clj/cljs files combined for readability):
(def ^:dynamic *trace* [])

(defn tracefn
  [n f]
  (fn [& args]
    (binding [*trace* (conj *trace* n)]
      (try
        (apply f args)
        (catch js/Object e
          (when-not (aget e "trace-printed")
            (prn *trace*)
            (aset e "trace-printed" true))
          (throw e))))))

(defmacro deftraced
  [sym bindings & forms]
  `(def ~sym (tracefn '~sym (fn ~bindings ~@forms))))
This gave me the following trace:
[proxy-inv proxy-inv inv-ctx distribute get-distributed-value proxy-inv inv-ctx distribute]
This was good enough for me to hunt down my bug, but this is a terrible way to debug, and it costs runtime performance. Can anyone explain why I'm seeing only one of 8 function calls in my stack trace, or how to expand the trace so I can see it all? Also note that there's some laziness going on here, but I don't think it's central to my problem, otherwise my custom trace would be shorter.

abdullahibra19:01:52

@dnolen i have done this and got more information but i don't know how to proceed with it, can you help please in this, this is my code https://gist.github.com/aibrahim/8090245f967958045e5d6253ca83bc08 and this is js code i try to port to cljs https://codepen.io/braintree/pen/MyzXqG

manutter5119:01:55

@abdullahibra Are you familiar with the docs at https://clojurescript.org/guides/externs? You’ll need an externs file to fix this.

abdullahibra19:01:35

ah, worthwhile reading

abdullahibra19:01:27

Thanks I'll read it now then try again and if failed I'll get back here

dominicm20:01:51

I'm having some issues with self-hosted cljs. When clicking "Eval", I get this error:

TypeError: cljs.core.cst$kw$alt_DASH_impl is undefined

dominicm20:01:40

I'm using the approach outlined here: https://stackoverflow.com/a/51575204

thheller21:01:36

@dominicm looks like you are maybe compiling with :optimize-constants true?

dominicm21:01:37

@thheller I don't think so, unless it's a default?

thheller21:01:06

it defaults to true for :advanced builds yes

thheller21:01:12

but not otherwise IIRC

dominicm21:01:22

I am calling cljs.build.api/build with {:main , :output-to "static/tickapp.js", :output-dir "/tmp/fatjar-bootstrap1463727058928380932/cljs", :asset-path "/tickapp.out", :optimizations :simple, :source-map false, :closure-defines {goog.DEBUG false}}]

thheller21:01:22

and the eval part?

dominicm21:01:46

it's a button on the page, it evals the code on page. Source is available at https://github.com/juxt/tick/blob/master/docs/src/tick/docs/app.cljs 🙂

thheller21:01:13

the page isn't working for me at all. just a bunch of 404s, don't see any buttons 😉

thheller21:01:34

try compiling with :optimize-constants false though. maybe it defaults to true for :simple builds

dominicm21:01:21

I'll try it 🙂

dominicm21:01:09

@thheller bit concerned that you're hitting a 404 for https://juxt.pro/tick/docs/index.html as it seems to work in all my browsers :thinking_face:

thheller21:01:20

it is working now

thheller21:01:42

maybe loaded at a bad time or something

dominicm21:01:05

@thheller setting :optimize-constants to false has done it

dominicm21:01:37

oddly though, https://clojurescript.org/guides/self-hosting indicates that optimize-constants should work.

thheller21:01:06

optimize constants with :simple is a bit tricky, can create situations where it tries to create a constant before actually having defined what a keyword is

thheller21:01:26

it should work though, might just be something else not sure

dominicm22:01:31

@thheller thanks for your help getting this working 🙂 I don't feel like I could easily create a minimal repro for this, so I'll struggle to chase it up. But it's open source if someone really wants to report it (and I'm happy to answer queries)