Fork me on GitHub
#shadow-cljs
<
2019-04-16
>
thheller07:04:27

@hobosarefriends just install that specific version via npm?

briemens09:04:53

I wrote some code in shadow-cljs that I want to extract into a reusable library. What is the best way to go about? The code/lib will only be consumed from clojurescript/shadow-cljs itself. I prefer not to compile to a node-library or npm-module which requires explicit exports. Should I bundle it as a jar instead or just symlink the code? Thanks!

thheller09:04:28

you mean you want to package it as a CLJS library?

briemens09:04:54

That sounds about right šŸ™‚

thheller09:04:31

I currently recommend lein for that since shadow-cljs doesn't have anything built-in for that yet

thheller09:04:52

or you just use deps.edn with :local/root

thheller09:04:03

really up to you if you want to push it to clojars or not

briemens09:04:28

aha, thanks for the tip/hint. At least I read the docs properly šŸ˜‰

briemens09:04:52

I have some boiler plate stuff that I want to reuse. So cljs import/export would be awesome

thheller09:04:00

by far the easiest method is probably just using the :source-paths directly

thheller09:04:19

so :source-paths ["src/main" "../other-lib/src/main"]

briemens09:04:41

I will try that. That's probably all I need for now

briemens09:04:12

So I just create a deps.edn file next to shadow-cljs.edn

briemens09:04:44

:man-bowing: Thank you! I have something to dig into.

Mno12:04:55

Well I have more than 1 version installed because reasons

wonko713:04:57

Hi all! I know this is a stupid question, but my keywords are failing me for a google search: const parse = require('csv-parse/lib/sync') how does this translate as a :require ?

wonko713:04:58

thanks, got it šŸ™‚

šŸ‘ 4
wonko713:04:53

I expected this to work: (:require [csv-parse :as csv]) ... (def parse-csv (-> csv .-lib .-sync)) but .-lib is undefined

hoopes14:04:53

so i don't have hard data to back this up yet, but i seem to need to use shift-reload to get markup changes recently. I'll be happy to try to build a simple repro case, but was wondering if anyone had the same issue before i do?

hoopes14:04:22

i'm using chrome, and the js console is telling me it's reloading the appropriate modules

lilactown15:04:51

you might not have the correct reload hooks setup?

lilactown15:04:06

are you re-rendering your app on reload?

hoopes15:04:39

yeah, it was working - i think i had shadow 2.7.17 ? just upgraded

hoopes15:04:05

i will try to put together a simple proof app - i could totally be doing something stupid, but just wanted to see if that was a known issue.

hoopes15:04:13

it happened to a couple people on my team recently, is why i was asking. but we're all working on the same app, so could def be a code problem

lilactown15:04:08

I had a number issues after we upgraded to 2.7.x to 2.8.x due to the closure library update. I had to clear my build output and cache

lilactown15:04:47

Iā€™ll let @thheller comment because I think if there is an issue, he might want to peek at your .shadow-cljs folder so hold off on deleting that šŸ˜¬

thheller15:04:09

I'm gonna need more details ... actual errors with stacktraces or so

thheller15:04:22

hard to guess "random" errors

Nolan15:04:53

is there a particular way to invoke shadow-cljs from npm/`node` without a global installation? e.g. in some directory where iā€™ve just npm installā€™d with a package that declares shadow-cljs as a dependency. running shadow-cljs ... is showing shadow-cljs: command not found

Nolan15:04:25

but i see the bin key in package.json, which makes me think that should work

thheller15:04:31

no package should ever have a dependency on shadow-cljs?

thheller15:04:49

npx shadow-cljs should work

wizard 4
šŸ‘ 4
thheller15:04:22

shadow-cljs should always be in devDependencies though

Nolan15:04:43

right, sorry, it is a devDependency. apologies

Nolan15:04:07

Iā€™ll try with npx, i think thats probably what Iā€™m looking for

thheller15:04:39

FWIW even with a global install it will always use the version installed in the project itself

Nolan15:04:52

right, that I do know. Iā€™ve just been wading into building a project as part of a remote pipeline, and theres no global installation there, so the build.sh was failing. Didnā€™t want to redundantly install it globally. I feel pretty good about the npx addition, I think thatā€™s the secret sauce.

Nolan15:04:09

will know soon. Thanks a million again @thheller

thheller15:04:44

you can just call the ./node_modules/.bin/shadow-cljs directly too

šŸ‘ 4
šŸ™ 4
thheller15:04:08

but thats sort an implementation detail of npm so probably best to stick with npx

Nolan15:04:50

agreed, but thats good to know

Nolan15:04:59

npx was just the stuff. Huge appreciation for you @thheller!

hoopes16:04:29

@thheller fwiw, there are no errors - everythign looks just like it should, except i need a shift-reload to get markup changes to show up - i'll build the repro app (if i can). otherwise, if nothing off the top of your head, don't worry about it. thanks.

thheller16:04:49

> get markup changes to show up -

thheller16:04:55

what does that mean?

thheller16:04:06

I have no context for what you are doing

thheller16:04:10

I'm guessing react? reagent? re-frame?

thheller16:04:44

shift-reload? do you use the built-in dev-http servers? otherwise caching might be an issue? active service-worker?

thheller16:04:48

tooo many factors

hoopes16:04:37

yeah, sorry - using re-frame, changing some prop on a div (for instance), and it doesn't auto-show-up

hoopes16:04:56

the js console says it's reloading the module, but the DOM doesn't refresh

hoopes16:04:03

ignore me until i have something useful to tell you

thheller16:04:36

reloading the code doesn't do anything to your DOM

thheller16:04:45

you need a :dev/after-load hook to trigger a re-render

thheller16:04:12

if you are doing that you might need to also clear the re-frame subscription cache in that hook

hoopes16:04:29

ok, will try it out. thanks very much!

thheller19:04:46

@lilactown do you have a function/macro in hx that will just return a react element?

thheller19:04:02

ah hx/f right?

lilactown19:04:23

yeah. (hx.react/f [:div "asdf"])

lilactown19:04:04

the whole lib was supposed to be a clever setup for hxf = "hiccup transform" šŸ˜… kinda got lost along the way

thheller19:04:32

I'm running some benchmarks of cljs react wrappers since I wanted to compare my new one šŸ˜‰

dpsutton19:04:53

@lilactown was the f function one you wanted to rename recently?

thheller19:04:09

react x 3,449,728 ops/sec Ā±2.64% (93 runs sampled)
reagent x 398,044 ops/sec Ā±1.78% (93 runs sampled)
shadow x 1,851,920 ops/sec Ā±3.58% (94 runs sampled)
hx x 50,539 ops/sec Ā±1.04% (89 runs sampled)

thheller19:04:13

how come hx is so slow? šŸ˜›

šŸ˜‚ 4
dpsutton19:04:54

just wondering since you mentioned the original intent got lost

lilactown19:04:29

itā€™s a fair guess šŸ˜„ but this is what I want to rename: https://github.com/Lokeh/hx/pull/46

lilactown19:04:26

šŸ˜‚ Iā€™ve literally never benchmarked it. not surprised itā€™s slow

lilactown19:04:52

the hiccup parser is super naive

lilactown19:04:16

would you send me the benchmark you created at some point?

lilactown19:04:46

Iā€™d really like a starting point to start tuning hx

thheller19:04:53

just trying to render something simple that you may have in an app

thheller19:04:09

just wanted to get a baseline. mine is faster than react when running without NODE_ENV=production šŸ˜›

thheller19:04:24

getting sucked into the benchmark hole again ...

šŸ•³ļø 4
lilactown19:04:22

hm yeah. itā€™s going to take awhile to tease out why hx is so slow

lilactown19:04:33

the hiccup parsing does kind of a lot. lots of little corner cases itā€™s taking care of right nowā€¦

lilactown20:04:24

is shadow.grove.react macro-based?

thheller20:04:46

yes. can't get that fast with interpreted vectors

thheller20:04:18

react x 284,902 ops/sec Ā±0.31% (97 runs sampled)
reagent x 173,311 ops/sec Ā±1.83% (93 runs sampled)
shadow x 269,805 ops/sec Ā±1.73% (94 runs sampled)
hx x 42,893 ops/sec Ā±1.29% (91 runs sampled)
rum x 244,721 ops/sec Ā±0.58% (96 runs sampled)

thheller20:04:22

rum is doing pretty good too

lilactown20:04:56

isn't rum also macro-based?

thheller20:04:23

well in my trivial example it is, it also has an interpreted fallback. unsure how often that kicks in though

lilactown20:04:00

yeah. I think my goal for hx would be at least as fast as reagent šŸ˜›

thheller20:04:19

yeah it seems rather slow right now

lilactown20:04:33

I think that reagent does some caching behind the scenes

thheller20:04:48

could be. I'm surprised how fast it actually is

lilactown20:04:50

there's also a bunch of things that hx does to rewrite props as a JS obj that could be memoized

thheller20:04:21

would have expected it to be much slower as well given all the vector/map construction

lilactown20:04:50

yeah. I think it caches ā€œnativeā€ hiccup

thheller20:04:24

every time I look at :advanced compiled code I'm amazed at the optimizations closure does

wilkerlucio20:04:38

@thheller had you tested with Fulcro dom macros as well? I'm curious how it compares to the others

thheller20:04:49

oh good point. I'll add that

thheller20:04:33

@wilkerlucio doing excellent as expected

react x 281,008 ops/sec Ā±1.15% (96 runs sampled)
reagent x 170,642 ops/sec Ā±1.75% (93 runs sampled)
shadow x 269,498 ops/sec Ā±1.78% (96 runs sampled)
hx x 41,602 ops/sec Ā±1.26% (92 runs sampled)
rum x 244,612 ops/sec Ā±0.27% (97 runs sampled)
fulcro-dom x 262,460 ops/sec Ā±1.40% (95 runs sampled)

šŸ‘ 8
thheller20:04:19

@wilkerlucio FWIW the (fulcro-dom/div :.card ...) variant only seems to run interpreted and is much slower than {:className "card"}.

wilkerlucio20:04:19

interesting, and I think there is no reason for that, this could be generated at compilation time

wilkerlucio20:04:30

@U0CKQ19AQ do you see any thing blocking this?

wilkerlucio20:04:53

oh, actually, no it can't, maybe the non localized can, but the localized dom needs to see the dynamic var to determine which class is rendered (and use the correct prefix)

thheller20:04:05

I'm using fulcro.client.dom in the test. don't know about the localized stuff

thheller20:04:09

does that work outside components?

thheller20:04:56

updated the benchmark do be a bit more dynamic which makes fulcro slower. probably hitting a slow pass again

thheller21:04:07

react x 87,861 ops/sec Ā±1.61% (89 runs sampled)
reagent x 51,563 ops/sec Ā±2.03% (91 runs sampled)
shadow x 98,100 ops/sec Ā±0.11% (95 runs sampled)
hx x 6,055 ops/sec Ā±9.97% (94 runs sampled)
rum x 80,311 ops/sec Ā±0.33% (94 runs sampled)
fulcro-dom x 29,496 ops/sec Ā±1.83% (87 runs sampled)

thheller21:04:44

unsure how shadow is faster than react suddenly šŸ˜›

thheller21:04:22

probably map being slower than reduce

tony.kay21:04:35

@thheller the kw variant should be triggering the macro, which should be doing all of the processing at compile timeā€¦it should end up raw react in source

tony.kay21:04:57

that is how it is designedā€¦if it isnā€™t working, then it is a bug

thheller21:04:16

yeah dunno. I didn't investigate further.

thheller21:04:40

it probably was caused by me omitting the {} props

thheller21:04:11

so it tried to eval the args since the macro couldn't determine that

tony.kay21:04:13

Ah, yesā€¦if there are children it is impossible to know if the child is a function making props or a child

thheller21:04:43

react x 109,719 ops/sec Ā±0.73% (93 runs sampled)
reagent x 51,251 ops/sec Ā±2.37% (91 runs sampled)
shadow x 97,151 ops/sec Ā±0.12% (97 runs sampled)
hx x 6,039 ops/sec Ā±11.34% (94 runs sampled)
rum x 80,007 ops/sec Ā±0.91% (94 runs sampled)
fulcro-dom x 83,931 ops/sec Ā±1.78% (92 runs sampled)

thheller21:04:57

perf is good overall if you are careful enough

tony.kay21:04:07

so yes, if you want full performance youā€™ll have to include a literal empty map of propsā€¦docs should prob note that; however, the time in those functions compared to everything else is less than 2% of the timeā€¦so it is useless to optimize that IMO

tony.kay21:04:26

itā€™s one of those microbenchmarks that means little in real life

thheller21:04:47

yeah I like wasting time on irrelevant performance optimizations šŸ˜‰

tony.kay21:04:11

There are much more profitable things to optimize, though

thheller21:04:59

yeah but also much more complex probably šŸ˜‰

tony.kay21:04:41

well, and Iā€™ve already got some of them writtenā€¦just not released yet šŸ˜‰

tony.kay21:04:57

nowhere near tested and hardened enough

tony.kay21:04:19

but I expect Fulcro 3 to be about 10-25x faster on targeted refresh

thheller21:04:37

I'm messing with react hooks on the side currently

thheller21:04:41

and I really do not like them šŸ˜›

tony.kay21:04:54

perhaps moreā€¦I can eliminate path-meta, the client parser, integrate basis-t calcs into db->tree, eliminate the need to render from root. So, one of my complex apps can take 80ms to render a refreshā€¦I think thatā€™ll turn into something under 10.

tony.kay21:04:13

Funny: I actually really like hooks

thheller21:04:37

I like the idea too but building something even remotely complex is just super annoying

tony.kay21:04:59

at least what Iā€™ve played with. Iā€™ve got a useFulcro hook working that lets you use a plain function as a fulcro component

tony.kay21:04:15

oh, I would not use them for vanilla js/react šŸ˜œ

tony.kay21:04:44

but then I only use vanilla in baking

tony.kay21:04:17

I like that I can use a state hook to get a function that I can then use to do targeted props updates

thheller21:04:24

:rolling_on_the_floor_laughing:

tony.kay21:04:25

I can do that with the component-based ones too, of courseā€¦but it ends up just a little cleaner because useState doesnā€™t accidentally collide with other state

wilkerlucio16:04:27

@thheller I'm with you on the hooks thing, to me they feel like re-frame subscriptions adopted at react level scale, same scaling issues (hard to reason over time)

thheller16:04:15

my concern is that everything happens in the render function so if you aren't careful about allocation you end up allocating way too much garbage

thheller16:04:36

eg. (react/useState {:my {:initial "state"}})

thheller16:04:04

the map will be allocated in each render but only used the first time

thheller16:04:28

moving that to a def outside to safe the allocation just makes the code ugly

thheller16:04:17

useContext is pretty much the only thing that is much much much nicer

thheller16:04:30

all the other stuff is icky on some level šŸ˜›

tony.kay21:04:46

what garbage do you suspect with useState? Itā€™s stable stuff stored on the instanceā€¦Iā€™m not crazy about the ā€œorder dependentā€ implementation, but as a tool at the js level that we can wrap with better constructs Iā€™m not seeing the problem @thheller

tony.kay21:04:09

I reread your comment

tony.kay21:04:13

I see your point

tony.kay21:04:10

but then Iā€™m defaulting my values to nil, because there is no real component-local state I care aboutā€¦Iā€™m seeing it as a way to do ā€œsetPropsā€ on a component that causes a refresh without colliding with other ppls use of component-local state.

tony.kay21:04:36

and like you said, useContext is a hell of a lot better than lifecycle methods

tony.kay21:04:00

but less useful to me without the mechanism of useState

thheller21:04:05

yeah abusing useState as .forceUpdate is ok

thheller22:04:24

I feel we could do so much more with access to the underlying fiber handle though

thheller22:04:04

being limited to their hooks sucks since we could do cool tricks with macros to avoid all the stuff that otherwise can become costly

thheller22:04:30

but having worked with it a bit more I guess I'm indifferent. components have their pros/cons just like hooks

tony.kay01:04:54

Iā€™m hoping using hooks internally in Fulcro will reduce code size. Weā€™ll see. Iā€™m fine keeping the class-based stuff around (and of course kind of have to).

tony.kay01:04:21

but youā€™re right, having access to more internals as a documented and stable thing would be nice

wilkerlucio20:04:57

so fulcro and shadow ones are quite close

lilactown21:04:19

itā€™s funny how much variance hx has too

thheller21:04:49

probably allocating too much and running into GC issues

thheller21:04:58

I'm happy with my lib. Given that it isn't optimized for react but rather the replacement I'm building for it šŸ˜‰

thheller21:04:20

enough time wasted with benchmarks though