Sometimes you need to modifiy code depending on which target it is running in. Say you are writing a :browser
app but parts of the code should also work in :react-native
. The way I deal with this by abstracting out the relevant bits and either providing separate implementations of a protocol or just plain functions.
;; shared ns that defines the "interface"
;; with actual implementation added later
(ns my.app.env)
(defonce runtime-ref (atom {})
(defprotocol HostSpecific
(-something [impl foo bar]))
(defn something [foo bar]
(-something (:impl @runtime-ref) foo bar))
(defn just-a-fn [foo bar]
(let [actual (:just-a-fn @runtime-ref)]
(actual foo bar))
(ns my.app.shared
(:require [my.app.env :as env]))
...
(defn some-shared-fn [foo]
(env/something foo (some-thing-shared)))
only included in actual browser build (via :entries)
(ns my.app.browser
(:require
[my.app.env :as env]
[my.app.shared :as shared]
["react-dom" :as x]))
(defn that-fn [foo bar]
[::browser foo bar]))
(defn init []
(swap! env/runtime-ref assoc
:just-a-fn that-fn
:impl (reify env/HostSpecific
(-something [_ foo bar]
[::browser foo bar]))))
(ns my.app.react-native
(:require
[my.app.env :as env]
[my.app.shared :as shared]
["react-native" :as x]))
(defn that-fn [foo bar]
[::react-native foo bar]))
(defn init []
(swap! env/runtime-ref assoc
:just-a-fn that-fn
:impl (reify env/HostSpecific
(-something [_ foo bar]
[::react-native foo bar]))))