Fork me on GitHub
#clojurescript
<
2019-04-18
>
lilactown15:04:15

what kind of use cases do people have for including something like datascript in their app?

firstclassfunc15:04:35

All, struggling with the Clojurescript idiom that deals with child classes of Javascript libraries e.g.

class Foo extends Bar
. Am I missing something obvious?

lilactown15:04:45

so there’s not a super easy way of doing that in CLJS, since Clojure doesn’t really have first-class support for inheritance

lilactown15:04:49

the important thing to know is that class Foo extends Bar is JS syntax sugar on top of prototypical inheritance. so we can use the underlying prototype to do this.

lilactown15:04:47

another way of writing class Foo extends Bar would be:

Foo.prototype = Object.create(Bar.prototype);
Foo.prototype.constructor = Foo;

lilactown15:04:06

there are some helper functions in the goog.object namespace we might find useful:

(ns my-app.thing
  (:require [goog.object :as gobj]))

(defn Bar [])

(defn Foo [])

(gobj/extend (.-prototype Foo) (.-prototype Bar))

(set! (.. Foo -prototype -constructor) Foo)

👍 4
firstclassfunc16:04:02

Because Bar is a class I seem to have to use (defrecord Foo …)

lilactown16:04:52

I’m not sure what you mean.

lilactown16:04:09

classes are just functions

lilactown16:04:35

how are you trying to using Foo? where does Bar come from?

firstclassfunc16:04:58

its an object with methods on it. to expose the methods I had to use defrecord

lilactown16:04:20

an object with methods on it is not a class in JS

lilactown16:04:42

so sounds like you’re doing something a bit different.

firstclassfunc16:04:04

yes fair.. but the idiom you gave me does work

zane16:04:10

That might be good material for the cheatsheet.

dnolen16:04:08

And if you feel compelled to have more sugar - there's macros

☝️ 4
lilactown16:04:56

what does the ^not-native type hint actually do? I’m trying to optimize some paths that use a lot of a particular protocol, which is extended to native JS types (string, number, nil) as well as CLJS/user types like Keyword, PersistentVector, and Object

jstaab16:04:56

Hey there, I'm trying to optimize my bundle with shadow-cljs, in particular by trimming down cljs.core as much as I can. I've got a reproduction of just a small proof-of-concept here: https://github.com/staab/shadow-tiny The problem I'm running into is that if I use anything in core, my bundle blows up in size; currently I'm just invoking a couple core functions, and the size of cljs.core.js alone is 97k. Is there any way to improve this? I was thinking of maybe using refer-clojure in all my namespaces, but the docs say "The only options for :refer-clojure are :exclude and :rename". I'm also not sure if this would work, because it does appear that google closure compiler is properly tree-shaking things (`cljs.core.js` is only 1.1k if I remove the body of my main function, and my other project's cljs.core.js is 136k).

lilactown16:04:44

have you used the shadow-cljs build report?

lilactown16:04:55

it can give you better insight into what’s taking up space

jstaab16:04:14

I haven't on this project; I tried it on my main one yesterday and it crashed so I moved on

jstaab16:04:18

let me give it a quick go

lilactown16:04:31

that might a good thing to report if you have the time

jstaab16:04:39

This is my source code though:

(ns shadow-tiny.core)

(defn ^:export main []
  (print (map inc [1 2])))

lilactown16:04:12

I think what you’re going to run into is that the CLJS data structures weigh about 60-80kb un-gzipped

jstaab16:04:02

Ok, so I guess there's just not really a good way to avoid that

jstaab16:04:10

Is there a way to use a CDN for cljs core?

lilactown16:04:29

no, because it will tree-shake and remove things you don’t want

lilactown16:04:37

if you used a CDN for cljs.core it would be even bigger

jstaab16:04:51

Bigger, but hopefully aggressively cached

jstaab16:04:04

Preact/redux are a total of 5k (gzipped), and I'd like to get cljs to compete with that somehow

thheller17:04:47

do you have an example project showing this? I'd bet that the closure compiler can make this even smaller.

thheller17:04:22

without CLJS of course but it would be nice to show how irrelevant all the micro optimizations preact does are

thheller17:04:33

their obsession with size is extreme

jstaab16:04:20

it looks like my toy project is 88k gzipped

jstaab16:04:11

Is there any prior art on this you know of? I haven't been able to find any articles about tiny bundles online

lilactown16:04:52

preact and redux are much smaller in scope than CLJS (the language)

lilactown16:04:04

it’s comparing apples to oranges

jstaab16:04:40

It's true, but as far as delivering something to users, I'm more willing to suffer with js than bloat my bundles

lilactown16:04:27

for perspective, immutable.js is ~64K minified

jstaab16:04:51

Man, I love immutable data structures, but I'm not sure they're worth the cost

lilactown16:04:12

I think they are 🙂

lilactown16:04:23

88K is honestly not enough that I would start to balk. that’s not going to strain my users

jstaab16:04:37

hmm I think I'm misusing du too, it should be smaller than that

jstaab16:04:17

ls gives me closer to 35k

thheller16:04:35

@jstaab CLJS isn't really suited for "tiny" bundles since you are always going to end up with cljs.core and the datastructures

thheller16:04:47

its never going to compete with preact/redux

jstaab16:04:05

@thheller thanks for the confirmation, that's what I was beginning to suspect

thheller16:04:15

but it'll easily beat preact/redux/immutable/lodash

thheller16:04:28

which you are basically getting with cljs.core

jstaab16:04:47

do you have any strategies for alleviating the burden? I'd love to use it everywhere, and with cljs.core aggressively cached on a CDN that seems feasible

dnolen16:04:01

there's really not much more you can do

valtteri16:04:14

I’m setting up SPA routing without /#. I’ve configured webserver to always return index.html. Basic stuff works but I’m having trouble with nested routes like . My build tries to find /foo/js/compiled/out/goog/base.js when it actually exists in /js/compiled/out/goog/base.js. Same for deps.js and deps_cljs.js. What knobs I need to turn to make those paths absolute?

valtteri16:04:50

I got it figured out. I needed to set absolute path to :asset-path at dev time.

valtteri16:04:48

Under :advanced it just works as long as I’m pointing to the bundle with absolute pith in index.html.

thheller16:04:22

use code splitting .. but no CDN caching cljs.core is not possible

dnolen16:04:09

code splitting is the answer if you want to limit the initial payload - but fundamentally we start around 22K-25K gzipped and go up from there

dnolen16:04:26

given modern JS development - we are in fact very light weight

jstaab16:04:30

CDN caching is not possible meaning not supported/worth supporting, or is there something more fundamental going on with how it's linked?

dnolen16:04:40

and not really interested in investing more time beyond what Closure gives us

jstaab16:04:45

Ha @dnolen I've been reading some Henrik Joreteg lately and it's inspiring me to change that

dnolen16:04:56

but I don't really sympathize that much with such efforts - Closure fundamentally does the only interesting thing that can be done

dnolen16:04:05

the only JS project that understands this is Rollup

dnolen16:04:26

hand optimizing payloads is a massive waste of time IMO

jstaab16:04:25

I buy that for sure

jstaab16:04:25

Cool, thanks all for the answers, that was super helpful

dnolen16:04:04

Svelte is also interesting - but I can't find any data on that on really large projects

dnolen16:04:18

but my hunch is once you factor in all the dependencies you actually need, internationalization etc.

jstaab16:04:19

Svelte is interesting

dnolen16:04:24

it doesn't add up to much

jstaab16:04:32

yeah, I trimmed down my moment-timezone bundle yesterday

dnolen16:04:34

which is probably why don't find anyone bragging about non-toy stuff

jstaab16:04:35

saved me 800k

dnolen16:04:36

so suffice to say, I think ClojureScript and Closure are still state of the art, the real answer is make sure deps can be dead code eliminated

dnolen16:04:53

I think ClojureScript core is like 75,000-80,000 lines of generated JS or something

dnolen16:04:12

and you get 22K gzipped as the starting point

jstaab16:04:20

Yeah, that makes sense

jstaab16:04:44

If there were fewer macros, would bundle sizes shrink? I suppose run times would grow commensurately though

thheller16:04:57

macros don't contribute to bundle size at all

dnolen16:04:00

macros don't contribute

jstaab16:04:52

Really? I thought they were evaluated during build time, so if I had (defmacro x [] "blah blah blah") and used it a bunch, wouldn't the output be bigger? Or do you mean it's just negligible?

thheller16:04:43

the code they generate end up in the JS. the macros themselves don't.

thheller16:04:13

so yeah if you generate a bunch of code they can affect the bundle size if emit the same stuff over and over again

jstaab16:04:05

I see what you mean, the output would be the same whether you used a macro or manually wrote everything out longform, unless your macro is bloating the output unnecessarily

jstaab16:04:28

Anyhoo, thanks for your time, both of you

dnolen16:04:11

@jstaab right and if you don't use it, it will still get eliminated from the final build

ag18:04:51

has anyone done custom transitions with material-ui? Can someone point me at a snippet written in Clojurescript? I need to make something that can’t be done using default transitions: Collapse, Fade, Grow, etc. I don’t want to waste too much time learning all the intricacies.