Created
July 5, 2018 18:39
-
-
Save mk/45f22854c590139f42b6a12dbc3f1b54 to your computer and use it in GitHub Desktop.
Figwheel selective build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.nextjournal.build-tools.figwheel.dependency | |
(:require [clojure.tools.namespace.track :as ctn.track] | |
[clojure.tools.namespace.dir :as ctn.dir] | |
[clojure.tools.namespace.file :as ctn.file] | |
[clojure.tools.namespace.dependency :as ctn.dep] | |
[clojure.tools.namespace.parse :as ctn.parse] | |
[clojure.tools.namespace.find :as ctn.find] | |
[clojure.java.io :as io] | |
[clojure.tools.reader :as reader]) | |
(:import java.io.PushbackReader)) | |
(defn macro-dependency-nss | |
"Given a coll of cljs paths, return all namespaces that are being required | |
with :require-macros. Returns seq of symbol." | |
[files] | |
(with-redefs [ctn.parse/ns-clause-heads #{:require-macros}] | |
(into #{} | |
(comp | |
(map io/reader) | |
(map #(PushbackReader. %)) | |
(map ctn.parse/read-ns-decl) | |
(map ctn.parse/deps-from-ns-decl) | |
cat) | |
files))) | |
(defn macro-dependency-paths | |
"Given a coll of watch-paths (source directories) and a coll of cljs paths, | |
return all clj/cljc file paths that are required for macros, directly or | |
indirectly, and are part of watch-paths (i.e. only our \"own\" files.)" | |
[watch-paths cljs-paths] | |
(let [tracker (ctn.track/tracker) | |
scanned (ctn.dir/scan-dirs tracker watch-paths) | |
nss (macro-dependency-nss cljs-paths) | |
{graph ::ctn.track/deps | |
file->ns ::ctn.file/filemap} scanned | |
deps (and graph (ctn.dep/transitive-dependencies-set graph nss)) | |
ns->file (into {} (map (comp vec reverse)) file->ns)] | |
(map str (keep ns->file (concat nss deps))))) | |
(defn dependent-paths | |
"Given a coll of watch-paths (clj or cljs source directories) and a main | |
namespace (symbol), return all paths to clj/cljs/cljc files that are | |
required." | |
[watch-paths main] | |
(let [tracker (ctn.track/tracker) | |
scanned (ctn.dir/scan-dirs tracker watch-paths {:platform ctn.find/cljs}) | |
{graph ::ctn.track/deps | |
file->ns ::ctn.file/filemap} scanned | |
deps (ctn.dep/transitive-dependencies graph main) | |
ns->file (into {} (map (comp vec reverse)) file->ns) | |
cljs-paths (map str (keep ns->file (conj deps main)))] | |
(into #{} cat [(macro-dependency-paths watch-paths cljs-paths) | |
cljs-paths]))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.nextjournal.build-tools.figwheel | |
(:require [integrant.core :as integrant] | |
[figwheel-sidecar.system :as fw-sys] | |
[figwheel-sidecar.config :as fw-config] | |
[figwheel-sidecar.repl-api :as sidecar] | |
[figwheel-sidecar.components.cljs-autobuild :as fw-autobuild] | |
[com.nextjournal.build-tools.yarn :as yarn] | |
[com.nextjournal.build-tools.nodejs :as nodejs] | |
[com.nextjournal.build-tools.cljs-config :as config] | |
[com.nextjournal.build-tools.figwheel.dependency :as nj-fw-dep] | |
[suspendable.core :as suspendable])) | |
(def renderer-nodejs (atom nil)) | |
(defn start-renderer [] | |
(future | |
(Thread/sleep 1000) ;; allow files to flush to disk | |
(reset! renderer-nodejs (nodejs/run (get-in config/builds [:renderer :compiler :output-to]))))) | |
(defn wrap-build-fn--start-renderer [build-fn] | |
(let [start-once (delay (start-renderer))] | |
(fn [build-state] | |
(build-fn build-state) | |
(when (= (get-in build-state [:build-config :id]) "renderer") | |
(deref start-once))))) | |
(defn build-selectively | |
"Only trigger a Figwheel build when the changed file is a dependency of :main." | |
[build-fn build-state] | |
(let [{:keys [build-config changed-files]} build-state] | |
(if (seq changed-files) | |
(let [watch-paths (get-in build-config [:watch-paths]) | |
main (get-in build-config [:build-options :main]) | |
dependents (nj-fw-dep/dependent-paths watch-paths main)] | |
(when (some #(contains? dependents %) changed-files) | |
(build-fn build-state))) | |
;; initial build, always run | |
(build-fn build-state)))) | |
(defn wrap-build-fn--build-selectively [build-fn] | |
(fn [build-state] | |
(build-selectively build-fn build-state))) | |
(defmethod integrant/init-key ::figwheel [_ _] | |
(if-not (get-in sidecar/*repl-api-system* [:figwheel-system :system-running]) | |
(sidecar/start-figwheel! (assoc (config/figwheel-config) | |
:cljs-build-fn | |
(-> fw-autobuild/figwheel-build | |
wrap-build-fn--start-renderer | |
wrap-build-fn--build-selectively))))) | |
(defmethod integrant/suspend-key! ::figwheel [k s] | |
#_(integrant/halt-key! k s)) | |
(defmethod integrant/resume-key ::figwheel [k c _ _] | |
#_(integrant/init-key k c)) | |
(defmethod integrant/halt-key! ::figwheel [_ _] | |
(sidecar/stop-figwheel!) | |
(if-let [stop-nodejs (some-> @renderer-nodejs :stop)] | |
(stop-nodejs))) | |
(defmethod integrant/init-key ::renderer-dependencies [_ _] | |
(yarn/install "journal/renderer" "journal/renderer/compiled/out/node_modules")) | |
(defmethod integrant/suspend-key! ::figwheel [_ _] | |
(alter-var-root #'sidecar/*repl-api-system* suspendable/suspend)) | |
(defmethod integrant/resume-key ::figwheel [_ _ _ _] | |
(alter-var-root #'sidecar/*repl-api-system* #(suspendable/resume | |
(fw-sys/create-figwheel-system (config/figwheel-config)) | |
%))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment