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 is a website building & hosting documentation for Clojure/Script libraries
× close