Fork me on GitHub
#clojurescript
<
2016-11-12
>
rauh11:11:12

Is there a compilation of approximate code sizes (minified,compiled, gzip'ed) of various cljs libraries? Like core.async, datascript, reagent etc.

thheller11:11:41

@rauh there is no such thing, since it all depends on how much of those things you are using

thheller11:11:19

say datascript provides some functions you do not use

rauh11:11:21

I know, but basically a rough idea... core.async was much smaller than I expected e.g

thheller11:11:39

most of the core.async magic is macros

rauh11:11:59

I think it'd be helpful to have a rough idea in general... Is it 2kb or 50kb, helps a lot to make a decision

thheller11:11:14

so the lib itself does not carry a lot of code, yet the macros may produces huge amounts of code in your js files

rauh11:11:33

Yeah datascript doesn't get DCE very well. Lot's of datastructures and most of the functions are ^:exported

thheller11:11:51

as I said it is impossible to give an estimate like that since it will vary greatly depending on each project

thheller12:11:21

rough estimate would be really rough

thheller12:11:29

like +/- 50% rough

rauh12:11:35

I have to disagree that it's impossible. To get a general idea, we can just call the most common functions and then see how much code it added

thheller12:11:03

yes in theory

thheller12:11:19

but say you do not use clojure.string

thheller12:11:28

then you add datascript which uses it

rauh12:11:32

I'm at 2kb for core.async (using chan and go) and 30kb for datascript

thheller12:11:42

that gives you datascript+`clojure.string` size

thheller12:11:07

then you measure core.async and you get core.async+`clojure.string` size

thheller12:11:15

indiviually

thheller12:11:42

but if you use both you do not get (datascript + clojure.string) + (core.async + clojure.string)

rauh12:11:50

Well we could get smart about this and look at goog.deps.cljs (or so?) and see what's coming in (relatively)

thheller12:11:54

you get (datascript + core.async + clojure.string)

thheller12:11:17

that is the "high level" of namespaces

thheller12:11:27

since closure works on a much lower level

rauh12:11:33

I'd probably argue that the differences vary much more because of the compression algorithms getting more efficient the larger the file

thheller12:11:37

my argument is that the estimate would be useless

thheller12:11:58

also for core.async as an example

thheller12:11:17

files in out/core/async/... do not tell the whole story

thheller12:11:59

as code generated by (go (doseq [x some-seq] some very nested code)) can get extremely large

thheller12:11:26

but that will not be in out/core/async/... but in out/your/namespace/...

thheller12:11:45

so if you want to know how much a js lib is, measure in your project

rauh12:11:55

Yeah but that's something the developer should watch out for by doing an occasional macroexpand

rauh12:11:07

(Which I do and therefore avoid for completely)

thheller12:11:49

I understand why you'd be interested in the size, I know I am

thheller12:11:13

but given the experiences I had over the years, you cannot quite make general assumptions here

thheller12:11:38

what you can know exactly however

thheller12:11:00

is the size of external deps when using cljsjs for example

thheller12:11:08

as that is just js code that never gets optimized

rauh12:11:37

But the measures we'd get (using minimal examples) would be an upper bound (if calling most common API functions) so that'd be useful for many people IMO

thheller12:11:34

yeah but again, the measures might be way off due to the keeping/removal of namespaces that a lib uses

thheller12:11:43

but you might already be using yourself

thheller12:11:03

so you might see datascript is 50kb extra

thheller12:11:24

but you are actually already using 30kb of the code yourself

rauh12:11:34

If the upper bound says "100kb gzip difference" then it's not useful, but if it says 10kb it's already very useful

thheller12:11:36

so it would actually be 20kb

rauh12:11:19

I agree with what you're saying, but still think this information could be useful

thheller12:11:13

I'm not aware of any information like that

martinklepsch17:11:42

I think the only way to get this information is to constantly monitor file sizes of your build, then when you notice big changes you should investigate what caused them. Was thinking to make a boot task that tracks filesizes in git metadata (so it's associated with revs) but didn't do anything in that direction yet

rauh17:11:32

@martinklepsch That's actually what I've been doing for a few months. There is a :watch-fn that gets called each time a build is done. I then pipe it to nginx and get the brotli+gzip sizes of the builds and (spit..)-append it in a file to keep a history of file sizes

martinklepsch17:11:22

I think that's the best you can do really (besides extending that basic approach with graphs etc). Because Closure removes code on a per-function basis it's impossible to give modules a fixed size

dnolen17:11:09

trying to compute the average size of a library doesn’t make sense

dnolen17:11:29

the only thing that does make sense is - "is this library broken for DCE to work correctly?"

dnolen17:11:04

once your dependency graph gets significantly deep such information is even less useful

dnolen17:11:15

since dependency C may make dependency B bigger depending on how you use C

cfleming18:11:01

Hi all, how should I require a package that has been bundled with browserify?

cfleming18:11:35

The equivalent JS is:

var blobStream = require(‘blob-stream’);
var stream = doc.pipe(blobStream());

anmonteiro18:11:10

@cfleming you need to add it as a foreign library

cfleming18:11:09

@anmonteiro So if it’s been bundled to bundle.js, I would do something like:

{:foreign-libs 
  [{:file “bundle.js"
    :file-min “bundle.min.js"
    :provides [”blobStream"]}]
 :externs [”bundle_externs.js"]}

anmonteiro18:11:34

@cfleming that's it. note, however, that :file is a filesystem path, not a classpath path

cfleming18:11:51

Right, that’s in the root of my project.

cfleming18:11:56

(for the moment)

anmonteiro18:11:00

in your ClojureScript namespace, you (:require [blobStream])

anmonteiro18:11:08

but that's just an artificial namespace

cfleming18:11:20

Oh, ok, so I can call that whatever I want?

anmonteiro18:11:23

you still need to get at the JS objects with js/ObjectThatTheBundleExports

cfleming18:11:47

And Closure will not try to run advanced mode over that lib, right?

anmonteiro18:11:58

they're just prepended to the output

raaon18:11:11

Hey new to Clojurescript. Here's some slightly surprising behavior when running code with advanced optimizations vs. not: ;; behavior when :optimizations :none (def inst #js {:foo "bar"}) (println (.-foo inst)) ;; => "bar" (println (aget inst "foo")) ;; => "bar" ;; behavior when :optimizations :advanced (def inst #js {:foo "bar"}) (println (.-foo inst)) ;; => nil (println (aget inst "foo")) ;; => "bar" I understand that this is b/c Google Closure renames symbols. So, I get it, this code is "incorrect". But why? Is the rule/contract that you should never use property access (.-foo inst) for dynamic Javascript properties? What's a better way to explain/understand this...?

anmonteiro18:11:50

@atdixon you can use property access if you have externs for that stuff

anmonteiro18:11:03

also goog.object/get is preferred over aget, which is meant for array access

dnolen18:11:14

@atdixon your conclusion is corrrect - and @anmonteiro suggestion is the way to go

dnolen18:11:34

if you’re using JSON values as dynamic data you need to use goog.object

dnolen18:11:03

for properties which represent code - fns, methods - these must be statically known

dnolen18:11:14

they are all subject to renaming

raaon18:11:11

@anmonteiro @dnolen perfect - thank you!

cfleming19:11:13

@anmonteiro I can’t get this to work, I must be doing something daft. Here’s what I have - I’ve browserified the packages into bundle.js following the instructions here: https://github.com/whamtet/cljs-pdfkit#setup. bundle.js is in the root of my resources, and I believe it’s being loaded since it complained when it was in the wrong location.

cfleming19:11:27

(i.e. I’m including the bundle.js in a script tag)

anmonteiro19:11:58

if you're using foreign-libs you don't need to add a script tag

anmonteiro19:11:17

but that alone might not solve your problem

cfleming19:11:51

Unfortunately the instructions in that repo are a little light on details.

cfleming19:11:46

So in bundle.js I see: function BlobStream() { ... and module.exports = BlobStream;

cfleming19:11:34

It looks to me like that library assumes I’ve put everything in a script tag, since for the PDF functionality he doesn’t seem to be using foreign libs.

cfleming19:11:58

BlobStream is only one of the deps in the browserify bundle.

cfleming19:11:26

Unfortunately the source to his demo doesn’t seem to be available.

cfleming19:11:08

Actually, he has another example which does have source available - I’ll check that out.

anmonteiro19:11:27

@cfleming I think foreign libs should be the same as a script tag

anmonteiro19:11:47

the ClojureScript compiler will order the dependencies such that your bundle comes before the code which requires it

anmonteiro19:11:34

oh, now that I think about it, if the library needs some (foreign lib) dependency to be there but it doesn't require it, there might be problems 🙂

cfleming19:11:46

Yeah, that’s what I think is happening

cfleming19:11:23

I think he’s browserified the whole lot, his lib requires the PDF stuff but I can’t see any evidence of him using foreign libs.

cfleming19:11:46

I think he just uses the script tag and then uses js/Whatever

cfleming19:11:34

@anmonteiro Got it, thanks - he’s using (js/require “blob-stream”), not foreign libs

anmonteiro19:11:08

heh OK. does the browser support js/require?

cfleming19:11:15

Apparently so

anmonteiro19:11:16

I suppose it's there just because of the browserified bundle

cfleming19:11:34

I guess, I don’t even have a vague idea how this stuff works 🙂

pvinis23:11:56

is there a sample project with reagent that i can look around?

pvinis23:11:41

would be nice if it also has a server part in clojure too, but not necessary