Is it expected that the namespace docstrings will be present in final release bundle?
My final bundle include https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc#L4 multiple times (92)
I believe there is something wrong with my build settings.
not sure why that would be any different in shadow-cljs, but I'll check it out
@souenzzo I pushed an update to HoneySQL that removes all those #' Var references. You'll have to use a the latest develop branch version via git deps to test it. https://github.com/seancorfield/honeysql/issues/596
No one has complained before, even when the performance overhaul was done, so I kept them that way as it made dev easier, but that's not a big enough deal to warrant causing problems with cljs and shadow-cljs 🙂
It would be nice if shadow-cljs didn't do that tho'...
ok, so the underlying issue is that vars in cljs don't really exist in the runtime. so whenever vars are used like #'format-expr is use a new var construct is generated by the compiler. this includes all the metadata of the var, and generates quite a bit of code.
new cljs.core.Var(
function () {
return honey.sql.format_expr;
},
new cljs.core.Symbol(
"honey.sql",
"format-expr",
"honey.sql/format-expr",
-761931772,
null,
),
cljs.core.PersistentHashMap.fromArrays(
[
new cljs.core.Keyword(null, "ns", "ns", 441598760),
new cljs.core.Keyword(null, "name", "name", 1843675177),
new cljs.core.Keyword(null, "file", "file", -1269645878),
new cljs.core.Keyword(
null,
"end-column",
"end-column",
1425389514,
),
new cljs.core.Keyword(null, "column", "column", 2078222095),
new cljs.core.Keyword(null, "line", "line", 212345235),
new cljs.core.Keyword(null, "declared", "declared", 92336021),
new cljs.core.Keyword(null, "end-line", "end-line", 1837326455),
new cljs.core.Keyword(null, "arglists", "arglists", 1661989754),
new cljs.core.Keyword(null, "doc", "doc", 1913296891),
new cljs.core.Keyword(null, "test", "test", 577538877),
],
[
new cljs.core.Symbol(
null,
"honey.sql",
"honey.sql",
335271223,
null,
),
new cljs.core.Symbol(
null,
"format-expr",
"format-expr",
-1508928093,
null,
),
"/Users/thheller/.cljs/.aot_cache/1.12.134/5FDF96E/honey/sql.cljc",
21,
1,
41,
true,
41,
cljs.core.List.EMPTY,
null,
cljs.core.truth_(honey.sql.format_expr)
? honey.sql.format_expr.cljs$lang$test
: null,
],
),
),this is from the regular compile. I guess shadow-cljs handles things differently and adds the doc metadata on symbol for the ns, which I know I did for a reason but can't quite remember what that was. will need to check, but it seems correct.
in essence you shouldn't be using vars in CLJS, since they are always noisy and "leak" a bunch of stuff. I don't think its ideal it leaks the entire path in cljs for example.
It seems to be related to the var usage:
HoneySQL uses many #'vars and seems that everytime that it uses a var, the docstring is included again.
https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc#L4
@thheller
I couldn't reproduce the problem in the raw cljs - it seems to be shadow-cljs related only.
A repository that reproduces the issue, with the output file ( --debug enabled)
https://github.com/souenzzo/shadow-cljs-issue-report
The main.js file has 95 matches of Primary API for HoneySQL 2.x
#'var isn't optimal for final builds, CLJS libraries should try to avoid this normally
@souenzzo are you saying that vanilla CLJS doesn't include docstrings for vars?
Yep. That's a #shadow-cljs issue. Seems that each var USAGE in shadow build includes the NS do string. (And I was not able reproduce it in vanilla cljs) I think that it could at least, dedupe this string (maybe add some metadata to allow an GCC optimization)
@seancorfield before//after
went from 140 to 58 ill test in a "realworld" project soon
nice!
only 8kb diff on gzip. shows how well gzip handled all those extra docstrings
In my 'real' app: Before: 5.83Mb//1.37Gzip After: 5.67Mb//1.36Gzip (1% improv) HoneySQL went from 5th place//229Kb, to 16th place//68Kb in shadow-cljs report.
5mb yikes 😛
What are the main contributors to the 5mb if you are able to share?
src/cljs with 1.7Mb
clojurescript with 398 Kb
antd with 294 Kb
Note: we already use modules //code split
src/cljs 1.7mb..? seems a lot
~50kloc of code I tried searching to see if anyone had a metric between kloc and bundle size, but I found almost no data.
I mean, src/cljs seems to be coming from CLJS? or wait, this is your classpath dir, now I get it
For a #'var, cljs emits:
new cljs.core.Var(_, _, new cljs.core.PersistentArrayMap(null, 8, [cljs.core.cst$kw$ns, cljs.core.cst$sym$hello$lib, ___]))
(replaced irrelevant parts with _ )
While shadow-cljs emits
new cljs.core.Var(_, _, new cljs.core.PersistentArrayMap(null, 8, [cljs.core.cst$kw$ns, cljs.core.with_meta(cljs.core.cst$sym$hello$lib, __DOCSTRING_HERE__), ___]))
that's the difference @thheller
I'm just sharing my findings - I don't know if it's something that can (or should) be fixed.
But I was really curious to understand what the difference was between cljs and shadow.
I mentioned this yesterday. Can't remember why I changed this, but it was for a reason
1.7mb does seems like a lot indeed. can't all come from docstrings right? 😛
Would it be possible to deduplicate this code? I remember GCC having the ability to identify a duplicate block and moving it to a single definition + multiple usages.
usually doesn't matter at all. compression does that for you already.