This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-02-08
Channels
- # announcements (2)
- # aws (1)
- # beginners (134)
- # calva (26)
- # cider (48)
- # cljdoc (41)
- # cljs-dev (12)
- # clojure (178)
- # clojure-brasil (1)
- # clojure-europe (16)
- # clojure-italy (30)
- # clojure-nl (13)
- # clojure-spec (118)
- # clojure-uk (81)
- # clojurescript (209)
- # community-development (77)
- # cursive (7)
- # datomic (23)
- # duct (6)
- # emacs (15)
- # events (2)
- # figwheel (13)
- # figwheel-main (18)
- # fulcro (4)
- # jackdaw (4)
- # jobs (6)
- # jobs-discuss (6)
- # kaocha (2)
- # lein-figwheel (3)
- # off-topic (4)
- # other-languages (22)
- # pathom (2)
- # pedestal (9)
- # perun (10)
- # portkey (1)
- # re-frame (41)
- # reagent (6)
- # reitit (4)
- # remote-jobs (1)
- # ring-swagger (6)
- # rum (5)
- # shadow-cljs (300)
- # sql (3)
- # test-check (6)
- # testing (7)
- # vim (1)
- # yada (9)
I’m looking for some insights on using React. It seems to be a go to library that cljs embraces and wraps. Am I crazy, or is “setState” incredibly coupled to the UI? I’m interested if anyone has suggestions with respect to management of non UI state. I’m finding it hard to deal with non DOM/SVG state.
I feel like datascript solves this problem, but it would be interesting if a seasoned dev had some words of wisdom.
has anyone ever migrated a mature product from lein and figwheel over to shadow cljs? what was your experience? work is considering doing a late night trying to shift this over and I'm wondering if anyone has done this and if it is a single day type of goal or not
Not a huge thing, but decent size. I'm not sure there's much difference in effort relating to size, unless you do custom, weird stuff in project.clj.
Does anyone of you know how to find possible memory leaks with re-frame applications. we have app with React and Processing. The problem is that we have a Canvas element with Processing.js, but when we destroy it the Canvas elements are still in the heap. I tried to look into it but always end up at ReactDom or Processingjs object. What tools you guys use to debug such memory leaks?
No experience with this, but did you try taking Heap Snapshots?
https://dev.to/kepta/a-toddlers-guide-to-memory-leaks-in-javascript-25lf
And I know from the re-frame docs that subscribe
in a subscription leads to a memory leak.
The Wrong Way
You should NOT do this:
(re-frame.core/reg-event-db
:event-id
(fn [db v]
(let [sub-val @(subscribe [:something])] ;; <--- Eeek
....)))
Oh wait I see you did just that 🙂
It's sad to know that the UK parliament and government also have very few rules to prevent people being the bad guys, just as with the USA Congress, Senate and president https://twitter.com/CarolineLucas/status/1093655388636045313?s=19
wrong channel @U05254DQM?
Yes was supposed to be UK.
How many folks here use clojurescript on server side? Does it make sense, have enough support or Is it just a party trick?
I've been using node+cljs in http://www.daveconservatoire.org for years and I think works great
this one is open source if you like to check, altough code is quite old https://github.com/daveconservatoire/dcsite-cljs
@U066U8JQJ that is very cool. Has it catered to all your requirements ? For example imagine implementing a graphQL server .
yup, the interop with JS is very complete, you might need to write some wrappers but thats it
its actually easier to require NPM stuff on the server than it is on the client, since you can actually use the node.js require
@UD5AFCW4S for graphql, you might like to use: https://github.com/johanatan/speako
in pure cljs: https://clojars.org/speako
People also use CLJS for scripting in e.g. Planck, or Lumo or just cljs.main on NodeJS.
(require '[goog.dom :as dom])
(require '[goog.dom.forms :as forms])
(forms/get-value (dom/getElement "runAgainstTextarea"))
https://google.github.io/closure-library/api/goog.dom.forms.htmlDid you require goog.dom.forms
?
Yes adding it to “the top” should be enough.
Apos is just needed in REPL.
(ns mindmeld.core (:require [reagent.core :as reagent :refer [atom]] [reagent.session :as session] [reitit.frontend :as reitit] [clerk.core :as clerk] [accountant.core :as accountant] [reagent.core :as r] [goog.dom :as dom] [goog.dom.forms :as forms] ))
That looks OK.
No goog
is included in CLJS.
@its.ramzi @lukas.rychtecky it isn't forms/get-value
it is forms/getValue
Yeah! Sorry, @thheller is right!
@its.ramzi (.-value el)
will also just give you the value. no need for the goog stuff
Yeah for a simple textarea yes, but for selectbox is not so easy to get a value.
Is there a method I can use to identify which namespaces are taking a long time to (re)build? My reload is slow, and I'm not sure where to dig in.
@U04VDQDDY I've done this now, which got me further! I am not really seeing many stats, but I do see: > Process JS modules, elapsed time: 529.185744 msecs Does that mean that foreign libs is the cause? I don't think we have much of that
If you watch the :verbose
output, you may see spots where it seems to pause for a lengthy period of time
Fwiw, I do have an error about not being able to find @cljs-oss/module-deps, so it could be that?
Half a second could be in the range of reload times I see though. It's not giant, just not really quick. Maybe up to 3 seconds.
If you have :npm-deps
enabled, then it is possible that the compiler is spending a lot of time scanning the a large node_modules
tree. In that case, this patch might help give more insight https://dev.clojure.org/jira/browse/CLJS-2963
Oh, you said that reload is slow...
If you are referring to the :reload
flag to require
then perhaps more insight into what the compiler is doing could help.
If you are using Figwheel or Shadow CLJS, then there could be something going on in those tools.
At a certain point, it might help to just start adding diagnostic stuff into the tools / compilers in order to track down where it is spending time.
Putting the verbose flag on with Figwheel main didn't seem to output anywhere, which wasn't helpful
I also tracked down the module-deps thing, apparently just using foreign-libs is enough to cause that? Is that a bug?
Anyway, ns compilation: I have 1 ns alone which is a cljc of 1300 loc, That ns has 25 dependent nss which also have to be reloaded on this changing. So that will get big pretty quick.
Tried in #figwheel, but very low traffic there. Been running figwheel fine for months. Today when I try it on any project I get this:
This would seem to be an issue with use of non blocking IO, but I'm unclear on why this would start to happen now. This is on Ubuntu 14.01LTS. Still works fine on my Mac...
Any ideas appreciated
No, well, I don't think so. Isn't that new for 1.10?
Yeah, this thing appears to be using jline
OK, how do I do that?
Hmmm, looks like setting path :figwheel :readline
to false
disables. Let me try that
Well, that doesn't change things...
I really don't know the details of the infrastructure here - I am using lein-figwheel. Is jline not standard with this setup? I have done lein clean but that doesn't help. Or do you mean clean out lein-figwheel and figwheel and reinstall?? @john thanks for the help!
lein clean should do it. rebel-readline (and thus jline) comes pre-installed on some of the figwheel distros. (figwheel-main, at least, I think, though I could be wrong)... Though, I'd imagine a rebel-readline set to false should disable that.
@john as an FYI, the problem is with Google Chrome 72.0.3626.96, not sure if the next update will fix it but firefox works fine.
@john One line of thinking (from a couple of years back) was that there might be some ns
-form support or somesuch that might be added to Clojure to make it a bit easier to deal with aliased keywords (especially in the case where the namespace is just a name, not associated with a Clojure namespace). If that were added then that would be one less need for alias
in ClojureScript—we could just port that feature to ClojureScript and use it.
https://dev.clojure.org/jira/browse/CLJ-2123 https://dev.clojure.org/jira/browse/CLJ-2030
I'm building something akin to a lazy-ns
form that, if enabled in :clojure-defines
, will do a def for each referred var and hang the var off a (apply (resolve ...
in the def. (with some associated lazy cljs.loader/load semantics)... but if lazy is disabled in clojure-defines, I'll just default to requiring the namespace, with the associated vars referred in like normal. My only issue is the :as
clause. I don't yet have a way to simulate the aliasing.
But you could elide your lazy namespaces from the ns
form altogether, since you can require
at the top level anyway.
I think there is some code in the compiler that does some lightweight parsing of ns
forms in order to determine the partial compilation order... and that thwarts attempts to be fancy
Do you end up with an ns
form followed by a require
form? (That doesn't sound like it is something that is supported.)
Well, to be clear, the need for aliasing is so that I can get rid of the lazy-ns
thing altogether and just annotate hiccup forms with #lazy/comp
or some such, and I could do a form like #lazy/comp [some.lazy.ns :as sln :refer [foo bar] [foo "hi"] [sln/long-name "bye"]]
Well, the lazy-ns
thing just adds requires. No extra ns declarations, if that's what you mean
Cool cool. Just wondering if you're gonna end up fighting the static nature of the compiler
Really? It violates my mental model of how the compiler works. Interested in this now. 🙂
At its core is the fundamental idea that the compiler needs to statically determine the compilation order from, essentially, literal information in the ns
forms (or a top level require
form in its place if you want)
You could do really funky stuff like generate some code and then unleash the compiler on it
so... The reason this is working right now is because... nothing is depending on this particular namespace I'm implementing in? The outputted js is indistinguishable from what it would be otherwise, but the dep graph is corrupted?
yeah, it could be that you just have (ns* (:require baz.core))
sitting in your code, all lonely
from the perspective of another consuming ns? I'll have to bang on it more, but for whatever reason, things seem to be working.
When people say "top-level" require
I suppose we need to further qualify the meaning to be, a reuqire
at the top of the textual file
I guess I could also build a tag literal that transforms the ns form directly, but then you'd have to wrap your ns form in another ugly form, so I can slip in the parameters 😕
Does it bother your mental model that the generated js of (ns foo.bar) (require 'other.thing)
is equivalent to (ns foo.bar (:require [other.thing]))
after compile?
Yeah, I should probably push out some bits to play with too, so you've got something to bang on
FWIW, the ürtext on this subject is at https://anmonteiro.com/2016/10/clojurescript-require-outside-ns/
Even then, there is the partial compilation order to worry about... this require
stuff seems to be useful outside of source tree compilation
It's strange how well it works then.. I'm going to have to construct a bunch of deps to see how all this plays out
In parse-ns
you can see that require
which gets turned into ns*
involves a recur
to keep looking for more require
forms
But, ns
, doesn't involve a recur
.
This matches António's article explaining that you can have either ns
or multiple require
s
talking about here? https://github.com/clojure/clojurescript/blob/r1.10.516/src/main/clojure/cljs/analyzer.cljc#L4320 Looks like it's only handling the no-ns case?
I want to say that having require
(or multiple require
) statements is useful in a file that forms the "root" of the dependency tree. (Because it is only for ns
forms that you can actually define namespaces that can be required.)
Yes, the code line you linked is handling multiple require
s. (I say multiple because of the presence of recur
in there.)
Oh, so what you are seeing is the emitted Closure require statements that makes ns
-followed-by-`require` look like a supported thing...
Interestingly, ns
-followed-by-`require`s looks like it is a mild extension to the existing code 🙂
well, it's a provide
, followed by a number of require
statements. But also the fact that it works is throwing me off... Though it hasn't been without rough edges, so I'm sure you're right that it may not work in the large
If you make use of a function that is pulled in by a require
that follows an ns
you may find that arity checks don't work
I could be wrong though... parse-ns
is just for the partial order, I'd guess, and there is other machinery at play when you actually go to compile a file.
My hunch is that compilation can occur in a way that violates the needed partial order, and you won't have analysis information present for the vars you are using.
Right. I'm thinking you could have some code like this:
(ns foo.core)
(require '[bar.core :as bar])
(bar/some-fn 1 2 3)
and I'd be worried about what is happening with bar/some-fn
(whether it even gets resolved), and if it does, whether the analysis metadata for some-fn
is available, so you know its arityIt is an interesting meta-idea on whether something like :closure-defines
could be used to drive conditional dependencies in a codebase. The desire for conditional :require
is an evergreen concept. I wonder if that maps to some sane concept down at the Closure layer.
Where if lazy? is false in the closure-defines, it'll revert from cljs.loader stuff to regular requires
It makes you wonder if there is some very constrained equivalent of that which could work in ClojureScript
@thheller The things that use cljs.loader are also transformed, if lazy is disabled... the defs just become defs to the applicable namespace's vars
Quarter-baked thought:
(ns foo.core (:require [config.core :as config]))
(when config/use-baz?
(require '[baz.core: as baz]))
(when config/use-baz?
(baz/some-fn 1 2 3))
where
config/use-baz?
is a goog-define
Seems very challenging.The above code looks enough like Clojure where you don't feel like it is introducing fundamentally new concepts. It is just relaxing the model a little.
But this already works #lazy/ns [(:require [this.that :as blah]) (ns some.ns (:require ....
where the tagged-literal transforms your ns form before it's even processed, so as to parameterize the top level ns form itself
It would just be nice to have a clean solution to the problem of conditionally requiring another namespace, if it could be soundly defined and could work with Closure, :aot-cache
, etc.
Well, now that we're on the topic, closure-defines has the constraint that vals must be numbers, boolean or strings... But, since cljs.edn is edn, we already know it's static, so it couldn't hurt to clojure.edn/read-string
on the vals on their way in.
(which is what I'm doing manually, but it'd be slicker if cljs came that way, since, like I said, it's an edn file anyway)
I may push out a tiny cljs-env
lib that takes care of all that for you, so you can refer in env
and pull data out like environ or config does it
But unfortunately, you've got to declare your whole env map in closure-defines as one string
@thheller to finish answering your points of contention: I'm not suggesting cyclic deps. And the main purpose of this would be for usecases where you know a thing will not be loaded on start up, like react components or whathaveyou
So, the async thing isn't an issue, as long as you control the start up of the thing doing the calling
If you really wanted to get advanced though, you could potentially build a loading system that gets called first, and controls the calling of main in whatever/main.js
, so that you could control all loading aspects of loading startup. That may allow us to slip in implicit loads prior to synchronous invocations, application wide
So, ideally, deps could be conditionally loaded, just in time, just prior to a synchronous js context of execution
But for right now, I'm just focusing on things that can explicitly be controlled by the user, like with react components.
Since there's so much confusion around whether these require
s outside the ns form will work, I guess I'll first provide an ns re-writing tagged-litteral, where it allows you to annotate which namespaces should be lazy. Then another tagged-literal for hiccup forms, which defer to a fallback component until the module is loaded.