Reducing bundle size effects by disabling data printers
Would it be possible to disables the custom data printer with e.g. a compiler constant? For instance, the re-frame-10x library lets you opt in to the library by setting a compiler constant. Maybe this library can do the same. That is to say, expose a constant for disabling the data printers. This should allow Google Closure to remove cljs.pprint from bundles.
I am requesting this because I noticed that data_printers requires cljs.pprint, which is nearly 100 kb in my bundle.
Okay, I have tested two strategies to help reduce bundle size impact:
- Avoid top-level data structures, since they hurt Closure DCE.[1]
- Create a
lambdaisland.deja-fu.prettynamespace, that importslambdaisland.data-printersand installs the pretty printers for DateTime object.
I then tested bundle sizes on the following very simple code.
(ns demo.core
(:require [lambdaisland.deja-fu :as fu]))
(defn ^:export init [])
Here are some statistics I have recorded.
| Context | Uncompressed size | Gzipped size |
|---|---|---|
| Require library, no patches | 263 KB | 58 KB |
| Require library, with patches | 122 KB | 27 KB |
| Do not require library | 96 KB | 21 KB |
[1] https://groups.google.com/g/clojurescript/c/3QmukS-q9kw/m/8Tyo0nd8-X4J
@rome-user I think that's a reasonable thing to explore. It's a small library, so it makes sense to avoid automatically pulling in relatively heavy dependencies (even cljs.pprint).
In your table above "Do not require library," means without deja-fu, correct? So with patches, deja-fu adds about 26 KB uncompressed and 6 KB compressed?
I'm a little loathe to remove top-level data structures, since the largest one appears to be lambdaisland.deja-fu/relative-time-patterns, which doesn't seem like it would add much to bundle sizes. If you found an elegant way to do it or if you found it makes a big difference, I'd be interested in exploring it, though.
@rome-user Anyway, thank you for all this investigation! It looks like we can shave off quite a bit.
In your table above "Do not require library," means without deja-fu, correct?
That is correct. It means compiling the CLJS code without (:require [lambdaisland.deja-fu :as fu])
If you found an elegant way to do it or if you found it makes a big difference, I'd be interested in exploring it, though.
In short, I wrap the large map inside a delay and deref it where it is used. This allows Google Closure to remove relative-time-patterns from code that never calls distance-in-words.
The tricky part about disabling data printers (i.e. avoiding having to bundle cljs.pprint) is finding out how to maintain backwards compatibility. The easiest approach is creating a namespace like so.
(ns lambdaisland.deja-fu.pretty
(:import (goog.date Date DateTime))
(:require [lambdaisland.data-printers :as data-printers]
[lambdaisland.deja-fu :refer [format LocalTime]]))
(data-printers/register-print LocalTime 'time/time (comp str format))
(data-printers/register-pprint LocalTime 'time/time (comp str format))
(data-printers/register-print goog.date.Date 'time/date (comp str format))
(data-printers/register-pprint goog.date.Date 'time/date (comp str format))
(data-printers/register-print goog.date.DateTime 'time/date-time (comp str format))
(data-printers/register-pprint goog.date.DateTime 'time/date-time (comp str format))
Then in code one can (require '[lambdaisland.deja-fu.pretty]). I don't like my method because it is a breaking change.