I just added a new feature to shadow-cljs
which generates a bundle-info.edn
file which contains detailed information about :browser
release builds.
The goal of this is to enable visualizations like this one:
- https://chrisbateman.github.io/webpack-visualizer/ - click “Try a Demo”.
Or any other kind of visualization you can come up with.
I have a demo bundle-info.edn
(127 KB or huge gist). This is from a test build with a large number of JS deps and barely any CLJS so don’t expect it to resemble a real-world example. All the output is accurate though.
With shadow-cljs@2.0.92
or later you can run shadow-cljs release your-build
and find the file in target/shadow-cljs/builds/your-build/release/bundle-info.edn
. Note that this is currently only enabled for :browser
builds but could be done for all.
File Structure
The basic stucture of the bundle-info.edn
file has two keys at the top
{:build-modules [...]
:build-sources [...]
:build-modules
The :build-modules
vector contains one entry per :module
created for the build. A :module
consists of the sources it included and the byte sizes. Each :sources
entry is a “resource-id” refering to the :build-sources
vector.
{:module-id :base,
:sources
[[:shadow.build.classpath/resource "goog/base.js"]
[:shadow.build.classpath/resource "goog/debug/error.js"]
...
[:shadow.build.classpath/resource "cljs/core.cljs"]
...],
:depends-on #{},
:constants-size 1698,
:js-size 142200,
:gzip-size 29750}
:depends-on
is a set of the :module-id
it depends on. :constants-size
is the raw size of all keywords/symbol constants in this :module
as they are all collected from the individual sources to avoid repetition. :js-size
is the raw :advanced
byte size. :gzip-size
is that JS gzip’d.
:build-sources
The :build-sources
vector contains one entry per source file in the build.
:build-sources
[{:resource-id [:shadow.build.classpath/resource "goog/base.js"],
:resource-name "goog/base.js",
:module-id :base,
:type :goog,
:output-name "goog.base.js",
:js-size 97323,
:source-size 97323,
:optimized-size 875}
{:resource-id
[:shadow.build.classpath/resource "goog/debug/error.js"],
:resource-name "goog/debug/error.js",
:module-id :base,
:type :goog,
:output-name "goog.debug.error.js",
:js-size 1797,
:source-size 1797,
:optimized-size 0}
...
{:resource-id [:shadow.build.classpath/resource "cljs/core.cljs"],
:resource-name "cljs/core.cljs",
:module-id :base,
:type :cljs,
:output-name "cljs.core.js",
:js-size 1238250,
:source-size 321953,
:optimized-size 134156}
...]
:resource-id
the one used in :build-modules :sources
. :type
may be
-
:goog
for Closure JS :cljs
-
:js
for ES6/CommonJS -
:shadow-js
fornode_modules
:optimized-size
refers to the :advanced
optimized filesize. A 0
may mean that all code was removed.
Note that this is not 100% accurate since the code may have been moved to other sources as well (Closure Code Motion). Its a pretty good indicator how much was removed/minified. cljs.core
goes from 1.18MB -> 131KB.
The :shadow-js
sources will not have an :optimized-size
since it will not be optimized by :advanced
.
The bundle-info.edn
should contain all the information required to build a nice visualization. I may do this myself and some point but I have so much other stuff I want to do and could really use some help.
Ideally this would be done as a standalone library that just takes the bundle-info.edn
as input and generates some kind of report as HTML/React.