Figwheel Main is intended to provide a cljs.main like command line
experience for ClojureScript that also provides the many features that
were first developed in lein-figwheel but better.
figwheel-main is a complete rewrite of original figwheel. All of the
above features have been improved significantly.
ring-defaults and allows
extensive configuration of the middlewareThe new architecture also makes it trivial to add your own development tools that can communicate from the server to your client.
Currently ONLY works for a browser and Node environments
Currently still undergoing heavy development. Stuff will most certainly change.
This documentation is incomplete and intended to help you take the new figwheel for a spin before its official release.
Get a working example up and running quickly with the figwheel.main template
It is assumed that you have perused https://clojurescript.org/guides/quick-start
First, make sure you have the Clojure CLI Tools installed.
On Mac OSX with brew:
brew install clojure
Now launch a ClojureScript REPL with:
clj -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.1.4\"}}}}" -m figwheel.main
This will first compile browser REPL code to a temp directory, and
then a browser will open and a cljs.user=> prompt will appear.
From here you can do REPL driven development of ClojureScript.
You can also use leiningen by adding it to :dependencies in your
project.clj and launching it like so:
lein run -m figwheel.main
With Rebel Readline for much better REPL experience
Figwheel main will automatically use rebel-readline-cljs it is
available. So you can get Rebel Readline behavior by simply adding it
to your dependencies.
clojure -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.1.4\"} com.bhauman/rebel-readline-cljs {:mvn/version \"0.1.4\"}}}}" -m figwheel.main
As of right now Rebel readline does create some startup overhead (hoping to correct this in the near future), so you may want to choose use it only when you are going to interact at the REPL.
Creating a build
To define a build which will allow you work on a set of files and hot reload them.
Ensure your deps.edn file has figwheel.main dependencies:
{:deps {com.bhauman/figwheel-main {:mvn/version "0.1.4"}
com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}}
;; setup common development paths that you may be used to
;; from lein
:paths ["src" "target" "resources"]}
Create a file dev.cljs.edn build file:
{:main example.core}
And in src/example/core.cljs
(ns example.core)
(enable-console-print!)
(prn "hello world!")
and run the command:
clojure -m figwheel.main -b dev -r
This will launch a REPL and start autobuilding and reloading the src
directory so that any files you add or change in that directory will
be automatically hot reloaded into the browser.
The -b or --build flag is indicating that we should read
dev.cljs.edn for configuration.
The -r or --repl flag indicates that a repl should be launched.
Interesting to note that the above command is equivalent to:
clojure -m figwheel.main -co dev.cljs.edn -c -r
Note: that if you want to add your own index.html file to host your
application, if you have added resources to your "deps.edn" :paths
key, as demonstrated above, you can place the index.html in
resources/public/index.html
If you need to configure figwheel.main, place a figwheel-main.edn
in the same directory that you will be executing it from.
If you need to override some of the figwheel configuration options for a particular build, simply add those options as meta data on the build edn.
For example if you want to have :watch-dirs that are specific to the
"dev" build then in dev.cljs.edn
^{:watch-dirs ["cljs-src"]
:css-dirs ["resources/public/css"]}
{:main example.core}
All the available configuration options are documented here: https://github.com/bhauman/lein-figwheel/blob/master/figwheel-main/doc/figwheel-main-options.md
All the available configuration options specs are here: https://github.com/bhauman/lein-figwheel/blob/master/figwheel-main/src/figwheel/main/schema.clj
Understanding of the Java Classpath can be very helpful when working with ClojureScript.
ClojureScript searches for source files on the Classpath. When you add
a re-frame dependency like so:
{:deps {com.bhauman/figwheel-main {:mvn/version "0.1.4"}
com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
;; adding re-frame
re-frame {:mvn/version "1.10.5"}}
:paths ["src" "target" "resources"]}
The source files in re-frame are on the Classpath and the
ClojureScript compiler can find re-frame.core when you require it.
Your sources will need to be on the Classpath so that the Compiler can
find them. For example, if you have a file
cljs-src/example/core.cljs you should add cljs-src to the :paths
key so that the ClojureScript compiler can find your example.core
namespace. It is important to note that the src directory is on your
Classpath by default.
In Figwheel, the embedded HTTP server serves its files from the Java Classpath.
It actually serves any file it finds in on a Classpath in a public
sub-directory. This is why we added target and resources to the
:paths key in the deps.edn file above. With target and
resources both on the Classpath the server will be able to serve
anyfile in target/public and resources/public.
The compiler by default compiles artifacts to target for easy cleaning.
It is custmary to put your index.html, CSS files, and other
web artifacts in the resources/public directory.
Unlike cljs.main, with figwheel.main you will not specify a
--repl-env node because the figwheel.repl handles Node.js REPL
connections in addition to others.
You can launch a Node REPL like so:
clojure -m figwheel.main -t node -r
You can quickly get a hot reloading CLJS node build up an running using the
deps.edn, example.core and dev.cljs.edn above. Simply add a --target node
or -t node to the compile command.
clojure -m figwheel.main -t node -b dev -r
This will launch a CLJS Node REPL initialized with example.core you
can now edit example/core.cljs and it will be hot reloaded.
Of course if you add :target :nodejs to dev.cljs.edn like so:
{:main example.core
:target :nodejs}
You be able to run the build more simply:
clojure -m figwheel.main -b dev -r
It is common to want to provide callbacks to do some housekeeping before or after a hot reload has occurred.
You can conveniently configure hot reload callbacks at runtime with metadata. You can see and example of providing callbacks below:
;; first notify figwheel that this ns has callback defined in it
(ns ^:figwheel-hooks example.core)
;; mark the hook functions with ^:before-load and ^:after-load
;; metadata
(defn ^:before-load my-before-reload-callback []
(println "BEFORE reload!!!"))
(defn ^:after-load my-after-reload-callback []
(println "AFTER reload!!!"))
The reload hooks will be called before and after every hot code reload.
You can supply a -pc or --pprint-config flag to figwheel.main
and it will print out the computed configuration instead of running
the command.
For example:
clojure -m figwheel.main -pc -b dev -r
Will output:
---------------------- Figwheel options ----------------------
{:ring-server-options {:port 9550},
:client-print-to [:repl :console],
:pprint-config true,
:watch-dirs ("src"),
:mode :repl}
---------------------- Compiler options ----------------------
{:main exproj.core,
:preloads [figwheel.core figwheel.main figwheel.repl.preload],
:output-to "target/public/cljs-out/dev-main.js",
:output-dir "target/public/cljs-out/dev",
:asset-path "cljs-out/dev",
:aot-cache false,
:closure-defines
#:figwheel.repl{connect-url
"ws://localhost:9550/figwheel-connect?fwprocess=c8712b&fwbuild=dev",
print-output "repl,console"}}
See the figwheel.main/start function and the figwheel.main/start-join functions.
Figwheel main comes with a helper Ring app that is served when there is no other html page to host the REPL JavaScript env.
If you are interested in contributing to this app:
First hit me up in #figwheel-main channel on the clojurians Slack so that we can coordinate a bit.
To work on the helper app:
Checkout this repository and change directory to the figwheel-main
directory where this README is located.
Then the command
clj -m figwheel.main -b helper -r
should launch a live development workflow for the Helper application.
tweaking the CSS
The CSS files for the helper app are located at
helper-resources/public/com/bhauman/figwheel/helper/css and you
should be able to edit them live.
working on the app itself
Both the server-side and client side code are located in
src/figwheel/main/helper.cljc and you should be able to work on them
live.
If you change the behavior of the CLJS in
src/figwheel/main/helper.cljc it will not be reflected in the actual
helper app until you compile with make helper
editing helper content
The helper app content is generated from the Markdown files in the
helper-content directory. You must compile the markdown with make helper-docs this currently requires ruby and kramdown (gem install kramdown)
keep it simple
The helper app is intended to be very simple in structure. We do not want to
add more dependencies and slow the startup time of figwheel.main,
and we also do not want to do anything that will interfere with the
users running code.
Figwheel Main aims to honor all the flags provided by cljs.main, as
of right now, your mileage may vary.
Copyright © 2018 Bruce Hauman
Distributed under the Eclipse Public License either version 1.0 or any later version.
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 |