A minimal Electric Clojure app, and instructions on how to integrate it into an existing app.
Dev build:
- Shell:
clj -A:dev -X dev/-main
, or repl:(dev/-main)
- http://localhost:8080
- Electric root function: src/electric_starter_app/main.cljc
- Hot code reloading works: edit -> save -> see app reload in browser
Prod build:
clj -X:build:prod build-client
clj -M:prod -m prod
Uberjar (optional):
clj -X:build:prod uberjar :build/jar-name "target/app.jar"
java -cp target/app.jar clojure.main -m prod
Deployment example:
- Dockerfile
- fly.io deployment through github actions: .github/workflows/deploy.yml & fly.toml
- Look at src-prod/prod.cljc. It contains:
- server entrypoint
- client entrypoint
- necessary configuration
- Look at src/electric_starter_app/server_jetty.clj. It contains:
- an example Jetty integration
- required ring middlewares
Electric Clojure programs compile down to separate client and server target programs, which are compiled from the same Electric application source code.
- For an Electric client/server pair to successfully connect, they must be built from matching source code. The server will reject mismatched clients (based on a version number handshake coordinated by the Electric build) and instruct the client to refresh (to get the latest javascript artifact).
- [src-build/build.cljc](src-build/build.clj bakes the Electric app version into both client and server artifacts.
- server Electric app version is baked into
electric-manifest.edn
which is read in src-prod/prod.cljc. - client Electric app version is baked into the .js artifact as
hyperfiddle.electric-client/ELECTRIC_USER_VERSION
- server Electric app version is baked into
Consequently, you need robust cache invalidation in prod!
- In this example, complied js files are fingerprinted with their respective hash, to ensure a new release properly invalidates asset caches. index.html is templated with the generated js file name.
- The generated name comes from shadow-cljs's
manifest.edn
file (inresources/public/electric_starter_app/js/manifest.edn
), produced byclj -X:build:prod build-client
. Watch out: this shadow-cljs compilation manifest is not the same manifest aselectric-manifest.edn
! - Notice that src/electric_starter_app/server_jetty.clj ->
wrap-index-page
reads:manifest-path
from config. The config comes from src-prod/prod.cljc.