Surfacing lazy module errors
Shadow-CLJS has a nifty lazy/loadable tool that helps with loading modules lazily in ClojureScript apps. I find it useful.
But one thing caught me off guard: errors thrown while loading modules via goog.module.ModuleManager
are swallowed silently, so if you happen to write a bug in a lazy-loaded module, goog’s module loader will retry a number of times in the background, and then, much later, print a message to the console that’s unrelated to the cause.
We can bring these errors to the surface by listening for a special “REQUEST_ERROR” type (which must be looked up at runtime) on the current ModuleLoader
instance:
(ns example.listen
(:require [applied-science.js-interop :as j])
(:import [goog.module ModuleManager ModuleLoader]))
(let [Loader (.. ModuleManager (getInstance) (getLoader))
event-type (.. ModuleLoader -EventType -REQUEST_ERROR)]
(.addEventListener Loader event-type
(fn [event]
(let [{:keys [error moduleIds]} (j/lookup event)]
(js/console.error (str moduleIds) error)))))
Alternatively, we can use Google Closure’s built-in logging facilities. This adds 1.5kb to a production build but presumably logs other useful things from other goog namespaces.
(ns my-app.glog
(:require [goog.debug.Logger.Level :as Level]
[goog.log :as glog])
(:import [goog.debug Console]))
(.setCapturing (Console.) true)
(.setLevel (glog/getLogger "") Level/WARNING)
Arne Brasseur (@plexus) has written more about using goog.log
: https://lambdaisland.com/blog/2019-06-10-goog-log