Problem using malli clojurescript instrumentation and shadow-cljs

Instrumentation is kinda tricky since it can affect all namespaces. The best way to go about this is via :preloads with a custom ns created for it.

(ns my.app.preload
  {:dev/always true}
  (:require
    [my.app] ;; must require all namespace here that potentially get instrumented
    [malli.instrument.cljs :as mi]))

(mi/instrument!)

The in your build config :devtools {:preloads [my.app.preload]}.

The {:dev/always true} always metadata on the ns ensures that this namespace is always recompiled. Although note that this can make your build a lot slower. It isn’t strictly necessary if the macro doesn’t emit changing code but since there is no reliable way to know what the macro does (from the shadow-cljs side) it might be best to always run it.

The my.app require ensures that the preload is actually compiled after all your app namespaces have been compiled. I know “preload” isn’t the best name here but you must do this to ensure that other namespaces aren’t still compiling when the macro runs.