Hi all! I’m converting my project from lein-figwheel to figwheel-main. Hot-reloading hadn’t worked for a while for some reason, and I thought it might be good idea to bring my project into the present. I’ve migrated the config, and the compilation and CLJS REPL works. But there’s something wrong with the watch/recompile mechanics. After I change a file in one of the :watch-dirs
directories, it is picked up by the watcher and compilation starts, but then nothing happens for a very long time:
[Figwheel] Compiling build all to "target/cljsbuild/public/js"
[Figwheel] Successfully compiled build all to "target/cljsbuild/public/js" in 39.085 seconds.
[Figwheel] Watching paths: ("src/cljs" "src/cljc" "env/figwheel/cljs") to compile build - all
[Figwheel:FINE] Build Inputs: ["src/cljs" "src/cljc" "env/figwheel/cljs"]
[Figwheel:FINEST] Figwheel.core config: {:watch-dirs ("src/cljs" "src/cljc" "env/figwheel/cljs")}
[Figwheel] Starting Server at <http://localhost:9500>
[Figwheel] Starting REPL
[Figwheel:FINE] Reloading clj files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel:FINE] Detected changed cljs files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel] Compiling build all to "target/cljsbuild/public/js"
[Figwheel] Successfully compiled build all to "target/cljsbuild/public/js" in 347.875 seconds.
The last four lines are after the change. Notice that the recompile takes almost 6 minutes, whereas the initial compile was around 40 seconds.
I don’t know how to debug this. No activity in the log file (if I configure one with :log-file
. :log-level
is set to :all
. The CPU is mostly idle during these 6 minutes, so I’m pretty certain not much compilation is going on.
Any ideas for how to investigate what’s happening here? (I’ll post config in the thread.)Thanks, @bhauman! I tried with cljs.main, and it delivers fast recompiles:
$ clj -M:figwheel -m cljs.main --compile-opts env/figwheel/resources/cljsmain-all.edn --watch src/cljs --watch src/cljc --compile
[...]
Copying file: [lots of files...]
... done. Elapsed 27.26382128 seconds
Watching paths: /Users/martin/c/v/foo/src/cljs, /Users/martin/c/v/foo/src/cljc
Change detected, recompiling ...
Compiling /Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc to target/cljsbuild/public/js/foo/views/home_page.js
Copying file:/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc to target/cljsbuild/public/js/foo/views/home_page.cljc
... done. Elapsed 4.864356377 seconds
One other thing I just tried is to go back to Leiningen for figwheel-main, which is what the rest of my project uses. Maybe there was an impedance mismatch there between the different profiles and aliases. Leiningen is black magic to me, but as I long as I provide enough bat wings and secret incantations it does in fact work.
With the same setup as before, but running under Leiningen, I now got this:
[Figwheel:FINE] Detected changed cljs files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel] Compiling build all to "target/cljsbuild/public/js"
[Figwheel] Successfully compiled build all to "target/cljsbuild/public/js" in 482.354 seconds.
[Figwheel:FINE] Reloading clj files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc" "/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel:FINE] Detected changed cljs files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc" "/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel] Compiling build all to "target/cljsbuild/public/js"
[Figwheel] Successfully compiled build all to "target/cljsbuild/public/js" in 6.114 seconds.
[Figwheel:FINE] Reloading clj files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel:FINE] Detected changed cljs files: ("/Users/martin/c/v/foo/src/cljc/foo/views/home_page.cljc")
[Figwheel] Compiling build all to "target/cljsbuild/public/js"
[Figwheel] Successfully compiled build all to "target/cljsbuild/public/js" in 5.835 seconds.
Notice that the first re-compile takes a long time, while the next two takes a few short seconds.By the way, hot reloading does work with :modules
, for me at least (provided the recompile finishes).
@msolli this is interesting, I think the aot-cache is what is happening here
figwheel disables it because it can cause big headaches. if you enable the aot-cache I think your compile times will be fixed up
there compile times should be the same for all of these setups
OK, so I’ve enabled AOT cache with :aot-cache true
in the compiler options. I also wiped the ~/.cljs/.aot_cache directory just in case.
I experience the same phenomenon: The initial compile takes 40 seconds, the first recompile takes 6-8 minutes, the subsequent recompiles takes 6 seconds.
I’m on Clojurescript 1.10.844, by the way. I’ve tried downgrading to 1.10.764, but the problem persisted.
I wish I knew how to get more insight in what the computer is doing during those 6-8 minutes. It seems to be mostly waiting, since there is hardly any CPU activity. I’ve rebooted it, and there’s not much else going on.
Just tried one more thing: I copied the config to a foo.cljs.edn file and ran lein fig -- --build foo --repl
(ie. not using figwheel.main.api
). It showed the same phenomenon of around 6 minutes recompile time after the first file change.
@msolli sorry for not getting back sooner
If the compile has started then it should be compiling during that time
another thing to look at is the options that are provided to the compiler by figwheel
you can get the compile options by providing the -pc cli option (before the other options) and it will print out the compile options being send to the cljs compiler
but it that doesn’t provide some insight then I’d say that there is probably some strange thing going on with paths or there is a bug in the dependency traversal algorithm such that its recurring on itself
but I’d have to really look at what figwheel is doing to make modules reloadable
@bhauman Thanks for getting back to me – much obliged! Here are the compiler options:
{:output-dir "target/cljsbuild/public/js",
:closure-defines {figwheel.core/load-warninged-code true,
figwheel.repl/connect-url "<ws://localhost:9500/figwheel-connect?fwprocess=4cb3df&fwbuild=all>"},
:modules {,,,},
:optimizations :none,
:aot-cache true,
:warnings {:munged-namespace false},
:preloads [vilect.dev
figwheel.core
figwheel.main
figwheel.repl.preload
devtools.preload
figwheel.main.system-exit
figwheel.main.css-reload],
:asset-path "/js",
:repl-requires ([figwheel.repl :refer-macros [conns focus]]
[figwheel.main
:refer-macros
[stop-builds start-builds build-once reset clean status]]
[cljs.pprint :refer [pprint] :refer-macros [pp]]
[cljs.repl :refer-macros [source doc find-doc apropos dir pst]])}
I’ve omitted the contents of :modules
, which is a map with 139 entries of the form:
:vilect.views.organization.processes.new
{:output-to
"target/cljsbuild/public/js/vilect.views.organization.processes.new.js",
:entries #{vilect.views.organization.processes.new}},
:munged-namespace false
is set because that prevents warnings when compiling namespaces that contain the word “new” (which is a reserved keyword in Javascript).This is how I start Figwheel:
(figwheel/start
{:id :all
:options {:modules (clojure.edn/read-string (slurp "cljsbuilds.edn"))
:output-dir "target/cljsbuild/public/js"
:asset-path "/js"
:optimizations :none
:warnings {:munged-namespace false}
}
:config {:watch-dirs ["src/cljs" "src/cljc" "env/figwheel/cljs"]
:css-dirs ["resources/public/css" "target/sass/public/css"]
:helpful-classpaths false
:open-url false
:log-level :all
:load-warninged-code true
:client-log-level :finest
}})
cljsbuilds.edn
is an EDN file with many entries like this:
:foo.views.home-page
{:output-to "target/cljsbuild/public/js/foo.views.home-page.js",
:entries #{foo.views.home-page}}
Relevant entry in deps.edn
:
:figwheel
{:extra-deps {com.bhauman/figwheel-main {:mvn/version "0.2.13"}
cider/piggieback {:mvn/version "0.5.2"}}
:extra-paths ["target/cljsbuild" "src/cljs" "env/figwheel/resources" "env/figwheel/clj" "env/figwheel/cljs"]
:main-opts ["-m" "nrepl.cmdline"
"-p" "7070"
"--middleware" "[cider.piggieback/wrap-cljs-repl]"]}
@msolli I think you should try cljs.main with the watch flag and see if you get the same compile time.
This may just be the way it works.
Hot reloading for modules doesn’t work if I recall correctly, my suggestion is that if you wan’t fast recompiles and hot reloading that you use a :main entry for dev and then break things into modules for prod.