I have a ClojureScript project with the following barebone frontend app (main
being the entry point):
(ns shadowman.app
(:require
;; [cljs-http.client :as http]
;; [reagent.core :as r]
))
(defn main
""
[]
(js/console.log "hi from browser"))
This compiles to an expected 95,2 kB. Once I uncomment [cljs-http.client :as http]
the total jumps to 299,7 kB; including reagent
further raises it to 457,4 kB. Since I'm not calling any functions from these namespaces, shouldn't the Google Closure compiler eliminate them as dead-code?
The relevant parts of my shadow-cljs.edn are as follows: (omitting only three other builds, which, I might mention, do use the libs that are commented out):
{:source-paths [;; "env/prod"
"src/server" "test" "src/browser" "src/common" "src/plibs" "target/classes"]
:dependencies [[reagent "0.9.1"]
[bidi "2.1.6"]
[com.taoensso/timbre "4.10.0"]
;; [org.clojure/clojurescript "1.10.520"]
[macchiato/hiccups "0.4.1"]
[macchiato/core "0.2.16"]
[macchiato/env "0.0.6"]
[mount "0.1.16"]
;; [cljs-ajax "0.8.0"]
[cljs-http "0.1.46"]
[hickory "0.7.1"]
;; [markdown-to-hiccup "0.6.2"]
]
;; :dev-http {3001 "public"}
:builds {
:spa-prod
{
:target :browser
:output-dir "public/js/compiled"
:asset-path "/js/compiled"
:modules {:app-comp {:init-fn shadowman.app/main}}
:compiler-options
{:optimizations :advanced
}}
}}
I get the numbers above by running shadow-cljs release spa-prod
. Unless I'm mistaken about what to expect from dead-code elimination something is wrong with this picture. If so I'll be grateful for any ideas on how to investigate it.
You can generate a build report to find out what your final build includes.
shadow-cljs and the Closure Compiler do not perform DCE for npm dependencies that were required by your build. Once they are included only basic DCE is done (ie. :simple
) which is not capable of fully eliminating code. This is done because :advanced
breaks too many npm dependencies. So in the case of reagent
it'll end up including react
and react-dom
by default which won't be eliminated even if reagent
is.
This is not limited to npm dependencies however. Not all CLJS code or even Closure Library code can be fully eliminated. Some code patterns just prevent DCE from ever kicking in. One example would be any defmulti/defmethod
which can't be removed.