This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-13
Channels
- # announcements (18)
- # babashka (52)
- # beginners (47)
- # calva (45)
- # clj-kondo (31)
- # clojure (18)
- # clojure-brasil (2)
- # clojure-europe (3)
- # clojure-sweden (25)
- # clojurescript (19)
- # cursive (15)
- # datalevin (11)
- # defnpodcast (2)
- # duct (1)
- # editors (1)
- # emacs (6)
- # gratitude (1)
- # introduce-yourself (6)
- # jobs-discuss (11)
- # leiningen (3)
- # lsp (10)
- # luminus (2)
- # off-topic (4)
- # podcasts-discuss (2)
- # reitit (2)
- # shadow-cljs (10)
- # sql (9)
- # xtdb (4)
Hi there - I'm looking to implement server-side rendering and running into an issue because one of my NPM dependencies, firebaseui
, utilizes the browser window
object. When I require the dependency e.g. (:require ["firebaseui" :as firebaseui])
, shadow is unable to compile the build. Is there a way around this?
Should I try to lazy-load the dependency so that I can check for js/window
before bringing the dependency into the build? If so, is there a way to lazy-load the NPM module directly, or do I need to create a standalone module my-app.firebaseui
that imports firebaseui
, then lazily load my-app.firebaseui
into the rest of my app?
I'm going to try ^ and report back on how it goes
It seems like even if I add a check for js/window
, then try to lazy-load a separate my-app.firebase
module containing the firebaseui
import, shadow-cljs
is still unable to compile. I could definitely be doing something wrong here - would appreciate your input. Here's a simplified example of what I have:
;; shadow-cljs.edn
{:builds {:client {:module-loader true
:modules {:client {:entries [my-app.client]}
:firebaseui {:entries [my-app.firebaseui]
:depends-on #{:client}}}}}
;;
(ns my-app.firebaseui
(:require ["firebaseui" :as firebaseui])
(defn init-firebaseui [] ...)
;;
(ns my-app.sign-in
(:require [shadow.lazy :as lazy])
(when js/window
(lazy (lazy/loadable my-app.firebaseui/init-firebaseui)
(fn [init-firebaseui] (init-firebaseui))))
I made an example a while ago how you could move host specific requires to a namespace that is dedicated to a specific host (eg. browser and then one for node)
so you'll need a second build regardless. :target :browser
isn't meant to run on node
If I have some lazy-loaded modules in the :target :browser
build, my Node build doesn't know that those modules exist. However, the Clojurescript compiler is still going to build the dependency tree and attempt to load those (undefined in Node) modules. As a result, my :node
build is failing to compile due to an error with macroexpanding shadow.lazy/loadable
on namespaces that don't have a module mapping. I believe the :modules
config is specific to :browser
builds and isn't supported for :node
builds, so this seems to be expected behavior
How should I approach making those modules compatible / ignoring those modules for the Node build? Is that something I should also handle via host-specific namespaces?
This is kinda hard to answer without knowing exactly how you are using all this and how you intend to do the server side render. You could use custom reader conditionals to eliminate any calls for shadow.lazy for example. https://shadow-cljs.github.io/docs/UsersGuide.html#_conditional_reading