This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-11-07
Channels
- # bangalore-clj (1)
- # beginners (255)
- # boot (29)
- # cider (16)
- # cljs-dev (13)
- # cljsrn (6)
- # clojure (200)
- # clojure-berlin (1)
- # clojure-dev (13)
- # clojure-dusseldorf (6)
- # clojure-greece (1)
- # clojure-india (1)
- # clojure-italy (1)
- # clojure-russia (33)
- # clojure-spec (28)
- # clojure-uk (27)
- # clojurescript (47)
- # cursive (32)
- # data-science (3)
- # datascript (1)
- # datomic (40)
- # emacs (39)
- # events (4)
- # fulcro (55)
- # graphql (16)
- # immutant (2)
- # luminus (2)
- # lumo (5)
- # off-topic (142)
- # onyx (50)
- # portkey (1)
- # re-frame (45)
- # reagent (80)
- # remote-jobs (2)
- # ring-swagger (3)
- # rum (9)
- # schema (3)
- # shadow-cljs (184)
- # spacemacs (3)
- # test-check (4)
- # unrepl (2)
- # yada (5)
do bad things happen if the watch loop is tightened to <500ms? (https://github.com/thheller/shadow-cljs/blob/1cf72884ac7ef0da51d4cdc7ada55fc78a5dd77f/src/main/shadow/cljs/devtools/server/fs_watch.clj#L42)
The hot loading delay is one of my biggest pains developing web apps in cljs. Is there a on-save
hook you can expose? Editor integrations could hook into that. It should also cause a massive speed increase by only reevaluating the forms that changed (as we would through repl).
My current workaround is a fn like
(defn with-reload [& _]
(my-app.frontend.core/mount-root))
that I wrap components I’m editing with and simply eval the top level form:
(with-reload
(defn my-comp []
[:div "abc"]))
This hack that saves me a lot of time during dev. Almost browser dev-tools-like responsiveness.the proof of concept did exactly that. on file save inform the compiler and have the compiler return compile information so the editor can show warnings/errors
LSP is a lot of work, if you just want a file-save hook I can probably add something http-ish where you post some data about which files were saved?
Thanks theller! Looks like the on-save
hook is low-hanging fruit and editor agnostic. Please add it!
http endpoint you can curl? do you have EDN support or would JSON be simpler? or just one line per file saved?
@U0567Q30W thoughts?
I went down this rabbit hole a while ago https://twitter.com/krisajenkins/status/811930122014093312 😉
In cursive you can connect to the shadow nrepl and send (shadow.cljs.devtools.api/compile :my-build)
to the REPL on keypress
I agree. This is more about removing latency for UI code. Chrome devtools is instant. The editor knows exactly when files are edited, and most editors know which files were edited. This allows us to get rid of the whole file-watching process, which should enable major improvements in reload speed.
Regarding compile per form, that’s essentially like top-level-form repl eval. Editors know the top level forms of files. So between saves, we could track all edited forms and compile them one by one. I think this will enable immense speed improvements.
that’s what I’m doing with the snippet above. As you can see it takes some wrapping, because we also want to call the reload-hook for the app to re-render the root ui component
It’s puzzling for me that compile times of entire projects are used as a significant measure when the major road blockers for DX lie in the waits between incremental compilation steps. It’s a bit like starting a clojure repl. It’s slow but the idea is that it will run forever. Once it’s up, it’s blazingly fast. In the long run, that’s what matters.
I think its a tooling issue. You can bind “reload-my-app” to a button in Cursive, which just sends the proper function call to the REPL
I have that for all my clojure setups, in CLJS live-reload+watch is usually good enough for me.
@U050RLRRQ and I discussed this. In his terms what’s needed is a) form-level change tracking and b) maintaining a dep graph per var. For forms without vars it could have get assigned an unique identifier in a). Instead of save, a keyboard shortcut evals all edited forms. Lastly, a after-eval
hook reloads the app. Yes, if the hooks are available, both are tooling features. cc @U0567Q30W
I usually just load-file
when I make changes in a file. clojure again though, it might be slower in CLJS.
@thheller yes it’s much slower. I’m glad we’re starting this conversation. Sometimes the hardcore tool developers are not the hardcore users. I’m glad we’re having the opportunity to share perspectives.
not really, its very rarely this slow. shadow-cljs handles this slightly differently and only recompiles files that changed and those that directly required it.
when I’m working on a framework level thing thats used in a whole lot of places I usually isolate the thing I’m working on because the usual “app” would just be annoying at that point
unfortunately everything I looked at consumed a whole lot more CPU (which translates to battery)
figwheel uses https://github.com/wkf/hawk, no idea if that is faster?
figwheel is similarly slow. With large projects I had waits of 8+ seconds. Possibly because the cljs compiler has :recompile-dependents true
by default, but it could also just be recompiling all the project-owned namespaces required in the files that changed. For UI development, this is very painful.
not a huge deal but am curious how it would feel to be faster. currently working on a thing where a typical incremental compile is 0.4-0.5s, changes appear to show up on average 1.5s
looking at the browser and nothing happens, switching back only to realize I wasn’t patient enough
that surprised me when testing on windows the other day. it felt pretty much instant there.
How do people here work with libraries like for example om which need cljs.react and when you use npm-deps which needs react?
@mitchelkuijpers see https://code.thheller.com/blog/shadow-cljs/2017/09/15/js-dependencies-going-forward.html#breaking-change-removing-foreign-libs-support
more examples here https://github.com/mhuebert/shadow-re-frame/tree/master/src/cljsjs
using hawk is pretty straightforward and actually a whole lot faster (on OSX, did’t test others yet)
not super critical though. I might just add a config option to switch between the two mechanisms
Ah ok thnx let me see if I can fix this
That works like a charm thnx @thheller
just pushed [email protected]
which uses hawk
to watch files
but I think this is good enough while providing some safety that batch saves do not trigger 2 separate compiles
I also made a small compiler improvement earlier today which should make it about 20% faster overall
Anyone else ran into: The required namespace "com.rpl.specter.navs" is not available, it was required by "com/rpl/specter.cljc".
I found this issue https://github.com/nathanmarz/specter/issues/72 but i don't run bootstrapped clojurescript
It only happens when I do compile instead of watch
https://github.com/nathanmarz/specter/blob/master/src/clj/com/rpl/specter/navs.cljc#L8-L9
Ah you have your own parser for the nice error messages?
I have my own because the default is pretty hard to work with, less painful to write a custom one.
fixed in [email protected]
Damn you are fast
Works!
The only thing I have now is that I have a lot of cljs.pprint
warnings is that normal or am I screwing up?
------ WARNING #40 -------------------------------------------------------------
File: cljs/pprint.cljs:3144:3
--------------------------------------------------------------------------------
3140 | ;;; This is the equivalent of (formatter-out "~:<~1I~@{~w~^ ~_~}~:>"), but is
3141 | ;;; easier on the stack.
3142 |
3143 | (defn- pprint-simple-code-list [alis]
3144 | (pprint-logical-block :prefix "(" :suffix ")"
---------^----------------------------------------------------------------------
js/cljs.pprint.*current-level* not declared ^:dynamic
--------------------------------------------------------------------------------
3145 | (pprint-indent :block 1)
3146 | (print-length-loop [alis (seq alis)]
3147 | (when alis
3148 | (write-out (first alis))
3149 | (when (next alis)
--------------------------------------------------------------------------------
------ WARNING #41 -------------------------------------------------------------
File: cljs/pprint.cljs:3144:3
--------------------------------------------------------------------------------
3140 | ;;; This is the equivalent of (formatter-out "~:<~1I~@{~w~^ ~_~}~:>"), but is
3141 | ;;; easier on the stack.
3142 |
3143 | (defn- pprint-simple-code-list [alis]
3144 | (pprint-logical-block :prefix "(" :suffix ")"
---------^----------------------------------------------------------------------
js/cljs.pprint.*current-length* not declared ^:dynamic
--------------------------------------------------------------------------------
3145 | (pprint-indent :block 1)
3146 | (print-length-loop [alis (seq alis)]
3147 | (when alis
3148 | (write-out (first alis))
3149 | (when (next alis)
--------------------------------------------------------------------------------
Not sure if it's a derp from me
I run from withing leiningen I'll investigate some more
Maybe I have a an old clojurescript or something weird
Should I not add clojurescript dep myself and rely on shadow-cljs?
Hmm does that work if you have macros serverside?
Yeah I already fixed a lot of issues there, but maybe not running from lein will be nicer
Yeah I saw a conflict about the shaded closure compiler
at least I can’t think of a reason why it would be. clojurescript version will have an impact but since everything else seems to work …
I saw I had two profiles with different shadow-cljs deps, maybe that is the issue
I think I am going to try without leiningen, that will probably save me lots of time
Hmm even without leiningen I get the same errors
I thinkg nothing:
I get this errors while it is trying to build:
Nov 07, 2017 5:39:45 PM clojure.tools.logging$eval347$fn__350 invoke
WARNING: failed to get source excerpt for jar:file:/home/mitchel/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/pprint.cljs at {:warning :dynamic, :line nil, :column nil, :msg "js/cljs.pprint.*current-length* not declared ^:dynamic", :extra {:ev {:name js/cljs.pprint.*current-length*, :tag js, :ret-tag js, :ns js}, :name js/clj
s.pprint.*current-length*}}
java.lang.NullPointerException
And then all the warnings start popping up
[cljs.pprint :refer [pprint]]
that is the require
/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/pprint.cljs
it is using the correct file
I thind these very weird warnings:
Nov 07, 2017 5:46:55 PM clojure.tools.logging$eval347$fn__350 invoke
WARNING: failed to get source excerpt for jar:file:/home/mitchel/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/pprint.cljs at {:warning :dynamic, :line nil, :column nil, :msg "js/cljs.pprint.*current-length* not declared ^:dynamic", :extra {:ev {:name js/cljs.pprint.*current-length*, :tag js, :ret-tag js, :ns js}, :name js/clj
s.pprint.*current-length*}}
java.lang.NullPointerException
at clojure.lang.Numbers.ops(Numbers.java:1018)
at clojure.lang.Numbers.minus(Numbers.java:137)
at clojure.lang.Numbers.minus(Numbers.java:3717)
at shadow.build.warnings$get_source_excerpts$make_source_excerpt__20342.invoke(warnings.clj:28)
at shadow.build.warnings$get_source_excerpts$iter__20344__20348$fn__20349$fn__20350$fn__20352.invoke(warnings.clj:43)
at shadow.build.warnings$get_source_excerpts$iter__20344__20348$fn__20349$fn__20350.invoke(warnings.clj:42)
at shadow.build.warnings$get_source_excerpts$iter__20344__20348$fn__20349.invoke(warnings.clj:41)
I run it like this btw: node_modules/.bin/shadow-cljs clj-repl
does that matter?
I have no warnings
Ah cool dit not know that
but that works
issues like this one https://github.com/braintripping/re-view/issues/8 used to cause trouble in the past
I see no weird things in the output
I don’t know how it would get into this :line nil, :column nil
situation (which causes the NPE)
HED] cljs/tools/reader/edn.cljs
[CACHED] cljs/reader.cljs
[CACHED] cljs/tagged_literals.cljc
[CACHED] cljs/analyzer.cljc
[CACHED] cljs/analyzer/api.cljc
[CACHED] om/next.cljc
-> Compile CLJS: cljs/pprint.cljs
<- Compile CLJS: cljs/pprint.cljs (2208 ms)
[CACHED] fulcro/client/logging.cljc
[CACHED] yahoo/intl_messageformat_with_locales.cljs
[CACHED] fulcro/i18n.cljc
[CACHED] clojure/walk.cljs
#object[java.net.URL 0x62f11ebb "jar:file:/home/mitchel/.m2/repository/org/clojure/clojurescript/1.9.946/clojurescript-1.9.946.jar!/cljs/core.cljc"]
I am using om.next
could that break something?
[org.omcljs/om "1.0.0-beta1" :exclusions [cljsjs/react-dom cljsjs/react org.clojure/clojurescript]]
No problem, I have to go will play some more with it
Thank you for all the help though
Nuking the cache does not help btw
I'll try to reproduce with a smaller example
ran into a new problem. Code works in watch mode, but throws error after release build Uncaught Error: No protocol method ISwap.-swap! defined for type object: [object Object]
in http://repo.tiye.me/mvc-works/coworkflow/
however I had a bug in my build script and accidentally loaded "lib.js" twice, but without "main.js"
BTW are we going to use https://github.com/shadow-cljs now?
not knowing what to tell. I have no idea which things need explaining, in which order, etc.
for me shadow-cljs has covered nearly all my basic needs(except for dynamic import and CSS bundling) at currently. blogging won't help very much.
dunno what you mean by “dynamic import”. feel free to explain, I can take a look later.
I would like to learn your updates from Twitter(messages on slack also fine). I would reply to ask anyway when I want to learn more about the feature, as long as I know shadow-cljs supports it.
https://webpack.js.org/guides/code-splitting/#dynamic-imports actually I barely use it since my cljs projects are not large enough, just nice-to-have, my app always grows.