This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-01-09
Channels
- # adventofcode (1)
- # aleph (2)
- # beginners (28)
- # boot (26)
- # boot-dev (8)
- # cider (10)
- # clara (10)
- # cljs-dev (130)
- # cljs-experience (1)
- # cljsrn (12)
- # clojure (118)
- # clojure-austin (40)
- # clojure-boston (1)
- # clojure-chicago (1)
- # clojure-dusseldorf (1)
- # clojure-estonia (11)
- # clojure-france (1)
- # clojure-greece (3)
- # clojure-italy (19)
- # clojure-nl (1)
- # clojure-russia (1)
- # clojure-spec (19)
- # clojure-uk (34)
- # clojurescript (62)
- # core-logic (7)
- # cursive (11)
- # datomic (35)
- # emacs (15)
- # fulcro (264)
- # jobs (4)
- # leiningen (5)
- # midje (4)
- # off-topic (74)
- # onyx (27)
- # planck (14)
- # protorepl (4)
- # re-frame (37)
- # reagent (62)
- # rum (2)
- # shadow-cljs (171)
- # slack-help (5)
- # spacemacs (6)
- # specter (9)
hi all, if you don't mind a sneaky question: at work our project has 586 cljs files (not counting tests), 60K LOC total, including white lines these are the compilation sizes with most dependencies removed (as an experiment): :advanced = 3.5MB :simple - 13.2MB :none - 45MB again, this is just with core dependencies (React, Om, Sablono, core.async) and removing ~15 dependencies (and therefore some other transitive dependencies).
Not sure if this is the right channel. But to answer your question: You need to measure what namespaces are taking up the space. FWIW, i have a project about half the size with ~700KB output size. (W/o react though).
we don't get a source map to begin with 😞 I think it stops working past a size thanks for the measuring suggestion! I'll look at the directory tree with optimizations :none and note any outliers finally, I know what #cljs-dev is for, was hesitant about asking this but sincerely I find it a question few should be able to answer. as emphasized, I genuinely don't know if this can be considered a compiler issue
@thheller do you think one should use :default thing
with every CJS module also?
Maybe that'd be okay as the whole module support is still experimental
@juhoteperi :default
is a replacement for the directly invokable :as
. CLJS doesn’t allow directly invokeable namespaces and we added that as a hack for CJS that only have a “default” export (ie. module.exports = aThing
).
Yeah, but this also affects other functions, in addition to directly exported function
e.g. (:require [react-dom :as react-dom]) (react/render ...)
needs to call module$path$react-dom$react-dom["default"].render(...)
or should React-dom and other CJS modules be used with :default react-dom
?
Closure will export the CJS exports object as default property always
no matter if CJS exports object or function, it will always be the default property
I think it is to make interop between CJS and ES6 easy, inside Closure
Our solution is special case as we do the module processing as separate step and then use the processed JS as input files, instead of doing everything in one go
hmm indeed. I thought the intent was to make CJS look like ES6 and emulate the “default” export since that only exists when directly assigning module.exports
not with exports.foo
wonder how rewriting everything to module$path$react-dom$react-dom.default
instead of module$path$react-dom$react-dom
makes anything easier 😛
it is for ES6 -> CJS interop
Closure rewrites all ES6 to access default properties, so CJS modules need to export that
So they don't need to check on ES6 rewriting if the used module is CJS or ES6
I think I proposed just doing module$path$react-dom$react-dom.default = module$path$react-dom$react-dom
, so CJS modules would work as previously, at some point but that probably had some problems
CLJS_module$path$react-dom$react-dom = cljs.core.jsRequireInterop(module$path$react-dom$react-dom)
Hmm that could be easyish fix, as we now write provide/requires anyway
But would still require small change to analyzer/compiler to add those CLJS_ parts
except not, that can be done on :js-modules-index
default property can't be solved using that because the module name on js-modules-index is mangled so default is rewritten to default$
the jsRequireInterop
could test if the exported object only contains the .default
property and adjust accordingly
Yeah, I meant that this will solve that
I sort of hacked this in shadow-cljs
as well, https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/js.js#L74-L90
Ah interesting, I'll test this later today
@juhoteperi I would test for DCE issues when you try this. Aliasing is sketch-y for DCE or at least it was in the past.
@juhoteperi given that we know if a :require
is ES6 or CJS module, another approach would be to add default
via the compiler or at the REPL?
the JS world keeps coming up with new fun hacks … https://twitter.com/dan_abramov/status/950689118077571072
Opinion... is it a bug that (count (subvec [1 2] 0 1.5))
evaluates to 1.5
? (Clojure appears to round down in this case.)
This is one of those programs where it is difficult to claim whether it is even correct.
A practical motivating example is a function that attempts to return the fist half of a vector: (defn half [v] (subvec v 0 (/ (count v) 2)))
I'll log a JIRA so that more investigation can be done to determine whether it is a valid defect.
yeah but if your elements are 64 bit values, that’s nearly 256gb of RAM for that vector anyway
> However, the maximum length of an array according to the ECMA-262 5th Edition specification is bound by an unsigned 32-bit integer due to the ToUint32 abstract operation, so the longest possible array could have 232-1 = 4,294,967,295 = 4.29 billion elements.
Testing the module-name default property thing now. I can append some code to the modules, but I can't find easy way to change the code emitted when invoking functions from those modules.
:js-module-index
:name
probably shouldn't contain .default
because that needs to match with the module provide name
@juhoteperi any reason you can’t do this in :invoke
case in compiler?
I got a hacky solution working using emit* :var
: https://github.com/Deraen/clojurescript/commit/3103a0b29286d384dd1a2e979a945c0c48808c6f
Invoke wouldn't affect cases where just accessing a var?
@juhoteperi why all this aliasing stuff instead of ["default"]
?
I'm not sure at which point I could emit that. At the current location the value being emitted is map, munge maybe turns that into string which is then printed?
Advanced compiled Reagent output contains lots of mentions of ["default"]
This is output from Google Closure, yes. Not sure about DCE at all. But at least they don't munge the name.
with DCE here do you mean renaming or which optimization part?
as well as cross module code motion - so that stuff must work even if ["default"]
is present
I don't understand how accessing module fns/vars through one additional property would affect that (especially after I rewrite this without the additional if
on modules)
Yes, true. I'll try to understand the compiler part to properly emit default directly.
So something like this maybe:
(if (namespace n)
(emits (namespace n) "[\"default\"]." (name n))
(emits (name n) "[\"default\"]"))
Okay, got this version working: https://github.com/Deraen/clojurescript/commit/fbd20dd7e3d919e6ad784c5e38b25e43cb132d7a
Does var-name
check make any sense or is there better way to check if var is from JS module?
at this point var name is resolved to the full module$
so it is not easy to check against :js-module-index
I attached latest patch to the issue. Still seeing warnings about optimization passes, otherwise should be OK now.
Aha! Setting :language-in to :ecmascript-3/5 works, 6 or later doesn't. After this the optimized output is the same size as with 946.
Closure defaults to EcmaScript 2017 now, we should probably set default to 3 or 5 at Cljs side?
https://github.com/google/closure-compiler/commit/f6bcea3d151e9e441bc3b64f2eff00a794612878
(Compiler options page says default for both is es3, though default language-out has been no-transpile)
@juhoteperi yeah we need to change that, if we could get series of patches to bring us up to-date would definitely push this stuff through on Friday
I included languageIn default change on the Closure update patch
and opened PR on clojurescript-site to update the docs
@juhoteperi which tickets should I look at in which order to push this through?