True composition with cljs.main is achieved. cljs-reload does not wrap
cljs.main/-main and does not create a browser transport.
The extension seam is cljs.main -re cljs-reload.repl, the standard custom
REPL-environment option. cljs-reload.repl/ReloadEnv implements the public
cljs.repl protocols and delegates setup, evaluation, loading, teardown,
stacktrace parsing, error retrieval, browser options, and browser command-line
options to one stock cljs.repl.browser/BrowserEnv instance.
Its IJavaScriptEnv/-setup method runs inside cljs.repl/repl*, after
cljs.main has bound:
cljs.env/*compiler* atom;cljs.repl/*repl-env*;The watcher captures those values. Every reload rebinds them on its serial
worker and calls cljs.repl/load-file for each namespace in the calculated
order. The stock browser environment therefore reuses the existing browser
connection. There is no second compiler environment and no custom compile/eval
transport.
The browser REPL keeps one pending return-value callback. The decorator shares one re-entrant evaluation lock with the complete reload batch, preventing an interactive evaluation from interleaving with reload evaluations while still using the browser REPL's original request/response path.
-i, :init, and :inits were investigated but are not sufficient to own the
watcher. They are ClojureScript forms or scripts evaluated inside the target
JavaScript environment; the watcher and compiler atom live on the JVM side.
cljs.repl/load-file is sufficient for version 1. In ClojureScript 1.12.145 it:
goog.require with reload enabled.The library adds orchestration around that primitive, not custom compilation.
The only compiler-state intervention is a per-file snapshot and reset when
load-file throws. ClojureScript's own wrapped REPL special functions use the
same rollback pattern so a partial failed analysis does not poison recovery.
The graph is a hybrid of fresh compiler parsing and the active compiler state:
cljs.analyzer.api/parse-ns reads every .cljs and .cljc ns form below the
configured project roots when a reload is planned.:requires edges even when the active analyzer atom
still describes the previous successful compilation.cljs.repl/load-file then analyzes and compiles into the existing analyzer
atom.This uses ClojureScript's parser instead of implementing another ClojureScript reader. Reading ns forms afresh costs a project-source scan per logical save, but avoids the stale-analyzer bug where changing an ns form would calculate dependents from yesterday's edges. Content hashes serve both accurate change detection and native/editor event deduplication; mtimes remain in public state for familiar inspection.
Old and new dependent maps are combined while calculating affected namespaces.
That makes removal of an old dependency edge, source deletion, and namespace
rename visible to the plan. Only namespaces still backed by a source file can
appear in :reload-order; removed namespaces remain visible in :changed,
:affected, and :deleted.
The watcher is one daemon ScheduledExecutorService. It recursively polls the
configured source roots, compares content signatures, and waits for a stable
signature for :debounce-ms before invoking one reload. Polling is portable and
handles editors that save through temporary-file rename sequences without a
recursive native watch-key registry.
Pavlov and its bthreads were evaluated for orchestration. Behavioral threads are useful when multiple independent behaviors request, wait for, and block a shared event stream. Version 1 has one linear state machine—observe, debounce, scan, reload—so adopting a behavioral program would add a dependency and a second orchestration model without reducing complexity. The reload state itself remains ordinary maps, sets, and vectors in one atom.
cljs.main,
cljs.cli,
and cljs.repl
establish the lifecycle and reload primitive.IReplEnvOptions, IJavaScriptEnv, cljs.cli hooks,
analyzer state, and a watcher. cljs-reload needs only the standard browser
decorator, not Krell's React Native compilation and transport.cljs.main composition: yes.-re plus cljs.repl/IReplEnvOptions and
cljs.repl/IJavaScriptEnv delegation.cljs.repl/load-file sufficient: yes, for v1 and unoptimized development
output.cljs.main wrapper.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |