I needed project setup to support following workflow:
- The application running in development mode behave like application running in production (as much as possible). So all development code is addictive and excluded from production build.
- The application state keep running and reloading automatically on changes.
- Developer can easily extend development environment with any required tools.
So in about 2 years I've gradually built this prototype for my own needs.
- Leiningen based project.
- Code style settings for IntelliJ IDEA with Cursive.
- Integrant for application and development systems.
- Parallel start of integrant components.
- Separate sources for application and development code.
- Hot reloading on source files changes.
mountas integrant component for compiled dependencies in code.
- Configuration in JAVA properties files.
- Daemon interface to be run as service with
Immutantweb server with multiple webapps, single port, multiple hostnames.
- ClojureScript with Shadow CLJS (lein integration).
- React JS + Rum + Server-side rendering (SSR) + Passing component data from server
- Tailwind CSS
- Reload pages without Shadow CLJS (adapted
- Log database queries via
- Database migrations with
- Separate read-write and read-only database connections.
Why mount and integrant?
During migration of my setup from mount to integrant I found:
- that integrant is good for
- managing “big” components like web server, database connection pool and so on, which don't require direct reference in the code,
- managing multiple systems like application and development once.
- but passing integrant state around as map to access it from code is
- not so performant as mount,
- harder to trace dependencies in code using IDE's navigation tools.
So I decided to take best from both worlds and use mount and integrant simultaneously.
- Leiningen https://leiningen.org/
- Node.js https://nodejs.org/
- npm modules:
npm install --no-package-lock
Run for development:
Run to check build with release options:
lein clean lein with-profile test-release run
Run built release:
java -Dconfig.file=dev-resources/dev/config/default.props -jar ./target/uberjar/website.jar
Custom configuration properties can be placed in optional file (excluded from version control):