deja-fu icon indicating copy to clipboard operation
deja-fu copied to clipboard

Reducing bundle size effects by disabling data printers

Open rome-user opened this issue 2 years ago • 4 comments

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.

rome-user avatar Mar 11 '23 09:03 rome-user

Okay, I have tested two strategies to help reduce bundle size impact:

  1. Avoid top-level data structures, since they hurt Closure DCE.[1]
  2. Create a lambdaisland.deja-fu.pretty namespace, that imports lambdaisland.data-printers and 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 avatar Mar 12 '23 03:03 rome-user

@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.

alysbrooks avatar Mar 20 '23 14:03 alysbrooks

@rome-user Anyway, thank you for all this investigation! It looks like we can shave off quite a bit.

alysbrooks avatar Mar 20 '23 14:03 alysbrooks

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.

rome-user avatar Mar 20 '23 19:03 rome-user