Fork me on GitHub

It seems keyword definitions in ClojureScript are not efficient when using advanced compilation. Is this related to the way that ClojureScript used to define keyword? Can this be improved?


@cmal in :advanced keywords are also only allocated once.


It seems some of my keywords appears twice in the new function of my advanced compiled js file, probably because of the specs I used. So thanks @thheller


the keyword appears once but the keyword constructor uses keyword(ns, name, fully-qualified-name, hashcode) so in case of unqualified keywords the string appears twice.


that could indeed be improved but probably not worth after gzipping and the extra runtime overhead required


learned a lot. Thanks @thheller. That reminds me of the book of closure says the compiler's objective is the minimal size of gzipped file, not minimal size of compiled file.


it might be worth exploring though. keywords really add up, especially in reagent projects.


did a super quick comparison, just generating 200 keywords with the fqn and without


12kb vs 9.9kb “code”


4.4k vs 3.7k after gzip


even at 500 keywords its just about 2kb diff gzip’d and thats with completely random keywords


usually you’ll have some kind of overlap which should make gzip better


so yeah, possible micro optimization but probably not worth since you’ll then have to pay the overhead at runtime to construct the fqn when needed.


@cmal A few years ago the Closure compiler had an option to alias duplicate strings, i.e. create a var and use that. They removed that option since it was found to be no benefit in parsing time and code size after gzip.


Oh, it seems it still has that option.


yeah it does. I tried messing with it a while ago and pretty much got the same result they got.


It seems that secretary is a bit abandoned, no?


How do I add or replace a query parameter to the current browser location (without manual string writing)? Can I use Google Closure for this?


hmm, of course that doesn’t work because query parameters can have the same keys to represent an array

Roman Liutikov10:11:21

@borkdude have you tried goog.uri.utils ns?


a lot of people use secretary, and it is integrated in lots of popular lein templates, so i don’t think it’s risky to use it


@roman01la I’ve tried this in the browser console:

uri = new goog.Uri(window.location.href)
x = uri.getQueryData()
That kind of works, but doesn’t replace the query parameter yet. I think I’d have to do that manually as query params may have multiple by the same name.


I could first call x.remove and then add

Roman Liutikov10:11:38

goog.uri.utils.setParam(location.href, 'q' 'search')


That works, thanks! 🙂

Roman Liutikov11:11:55

it should also handle arrays, at least docs says it should 🙂

Roman Liutikov11:11:04

This works, goog.uri.utils.appendParams(location.href, 'q', ['1', '2', '3']), but not setParam


don’t need arrays, so setParam it is!


anyone using cljs.test in a 'fail-fast' manner? i.e. one test failure causes the rest of the suite to not be run


I see there's *report-counters*, but while in Clojure that's a real dynamic var, in Clojurescript it's a magic injected var


and I cannot use such vars if I want Figwheel to load my testing ns's into the browser (which is very convenient)


how come: (let [Initialization (aget ApplicationInsights "Initialization")] (Initialization. conf)) work and: (ApplicationInsights.Initialization. conf) does not?


@hkjels (ApplicationInsights.Initialization. conf) is not any syntax I recognize (looks like a mixture of JavaScript and ClojureScript). My first reaction would be (new (.-Initialization ApplicationInsights) conf) or something along the lines of what you did, (let [Initialization (.-Initialization ApplicationInsights)] (Initialization. conf)), if you wanted to allow Closure renaming (but that seems more verbose).


@mfikes your right, thanks.. Ending with a . is supposedly the same as (new x)


Yep. Dots at the beginning or end of a symbol are just sugar that the macroexpander converts. Try (macroexpand '(x.)) and (macroexpand '(.x y))


When doing prerender of a single page app in server. Let's say the server computes a reagent component to html, also adds the app.js script. All this gets downloaded by the browser, the prerendered html is put to the dom and then it downloads the app.js, parses it and recomputes+repaints that same component the server returned? If that so, then while the app.js is being downloaded + parsed + evaluated, the dom is still locked. Ok, you see the initial html but it is unusable. With re-frame or reagent you can't even put app.js script with async option as it uses document.write in its code, which makes async option not to work.

Roman Liutikov14:11:29

@tomaas yes. one thing you can do is to render as much interactive elements as possible with links and maybe some CSS. So while waiting for JS to load user can go to another page.

Roman Liutikov14:11:19

but then again you should wait for a bundle to load 😄


🙂 thanks, i think i'll focus on putting a really nice spinner instead of all this XD


@tomaas did you identify what is doing the document.write? seems like that should be fixed.

Roman Liutikov14:11:55

@tomaas haha, best solution ever! (seriously) you can do all sorts of optimizations like code splitting etc. but not sure if it’s worth it in your case


@thheller, I didn't. Just seen that there are a few appearances of it in production's (with optimization :advanced option) build.

Roman Liutikov14:11:13

@tomaas could you point to these in Reagent’s code? Just scanned the code base, couldn’t find anything


I didn't check on reagent, just re-frame (assumed it would be the same, sorry)


On reagent's build, I can see now only this


anyway, regarding the ultimate user experience I don't see any bad thing about not having anything prerendered on the server, it's just that I noticed that google's pagespeed insights takes away ~20 points for not having the script tag with async option.


however, doesn't care about that at all

Roman Liutikov14:11:33

it’s fine unless you are all into “perf matters” Google advocating thing, IMO


no 🙂 I was just curious


@mikethompson My apologies for dropping off the face of the earth; thank you for the pointer and looking into this; I’ll get it working 🙂 thanks again


anyone know of cljs bindings for ?


Does anyone know, what’s the format that the constructor for uses as pattern? Is it some standard?


@grav Looks like there might be other things like Q for quarter. Seems odd they don’t just document or provide a link. Here’s what I was looking at:


@mfikes Thanks for the link! You’re right, there’s more to it than just what I found. But who needs docs when you’ve got the nice Javascript source 😉


I'm trying to :require npm dependency (uuid) in browser through figwheel, but it fails because the dependency is not compiled into single file - it's using "require" function. Anyone could help? 🙂


It's failing with "require is not defined" Reference error.


The problem is that in its package.json is:

"browser": {
    "./lib/rng.js": "./lib/rng-browser.js",
    "./lib/sha1.js": "./lib/sha1-browser.js"
which is ignored by compiler -> ends up with unresolved (untouched) require('./lib/rng').


RE: boot-cljs-test I am using crisptrutski/boot-cljs-test and it seems to be crashing because I do not have phantomjs installed locally. Is this correct behaviour? I reviewed the README and it does not suggest anything about installing phantomjs for this to work. The next question is, is this the preferred task for cljs tests or are people more commonly writing their own task?


Interesting. The answer seems to be on the README where it actually tells you that you need to install phantom.