A minimal Electric Clojure app based on Electric Starter App providing a server with multiple independent clients, routing and an XTDB-in-a-box database. Each client has its own dependencies and electric reactor.
Instructions are provided on how to integrate it into an existing app. For more demos and examples, see Electric Fiddle.
Run builds and execute using the npm scripts
Dev build:
- Shell:
npm run watch
or Repl:(dev/-main)
- http://localhost:8080 and http://localhost:8080/admin
- Electric root and configuration functions:
- Hot code reloading works: edit -> save -> see app reload in browser
Prod build:
npm run build-prod-client
npm run prod-server
or to run both in sequence:
npm run prod
Uberjar:
npm run build-uber-jar
npm run uber-jar
Deployment example: (not tested)
- 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/server/server_jetty.clj. It contains:
- an example Jetty integration
- routing
- required ring middlewares
Electric Clojure programs compile down to separate clients 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/*/js/manifest.edn
). Watch out: this shadow-cljs compilation manifest is not the same manifest aselectric-manifest.edn
! - Notice that src/server/server_jetty.clj ->
wrap-index-page
reads:manifest-path
from config. The config comes from src-prod/prod.cljc. - src/server/server_jetty.clj also provides the uri router to server up the clients.