Replicant is a data-driven rendering library for Clojure(Script). It renders hiccup to strings or DOM nodes. Over and over. Efficiently, without a single dependency.
no.cjohansen/replicant {:mvn/version "2025.02.02"}
Learn about using Replicant:
The user interface is a function of application state. Whenever state changes, call this function to update the UI. The function receives all application state and returns the entire user interface as hiccup data -- every time. State (data) in, hiccup (data) out. No local state, no atoms, no subscriptions, no networking. Just a pure function from data to hiccup.
Replicant's design goal is to make this programming model feasible.
Replicant is a rendering library. That's it. There's no state management, no async rendering, no networking utilities. There's just a single function that renders and rerenders your hiccup to the DOM in an efficient manner.
In 2013, React launched with the idea that your UI was just a function of your application state. I still believe this is the best idea the frontend development community has had in the past 20 years.
While working on Dumdom, Anders, Magnar and I discovered how to make functions such as event handlers data-driven, without making the library prescriptive.
Snabbdom taught me that components are not a necessary feature of a virtual DOM renderer. Life-cycle hooks can just as easily be attached to DOM nodes.
m1p spawned the idea that the rendering
library could resolve placeholders like [:i18n ::some-key]
during rendering,
eliminating an entire walk
through the UI - an idea that turned in Replican
aliases (whose name was inspired by
chassis).
Replicant interoperates nicely with anything that works on data. It has hooks that exposes DOM elements for interoperability with other libraries.
Interoperability with component libraries like React is technically possible through hooks, but not recommended. Virtual DOM libraries and frameworks are not lightweight enough that I would encourage anyone to use more than one of them in the same application.
Replicant was very deliberately designed to not include certain features popular in other rendering libraries, such as component local state (or components, for that matter). Enabling Replicant to render components written for other libraries would effectively introduce an escape hatch that would undermine Replicant's assumptions. Given that I don't see "reusable components across libraries and frameworks" as an attractive goal, this is not complexity I am interesting in taking on.
For truly reusable extensions of the browser you can use web components (like u-elements) and have Replicant render custom elements, e.g.:
[:u-tabs
[:u-tablist
[:u-tab "Tab 1"]
[:u-tab "Tab 2"]
[:u-tab "Tab 3"]]
[:u-tabpanel "Panel 1"]
[:u-tabpanel "Panel 2"]
[:u-tabpanel "Panel 3"]]
Replicant is stable, performant and feature complete. Its public APIs will not be intentionally changed. It's used in production by several apps.
Replicant performance is being tuned using https://github.com/krausest/js-framework-benchmark. See benchmarking instructions for how to run locally.
Want to help make it fast? Fix a bug? Awesome, please help in any way you can. Bug fixes should come with test cases demonstrating the problem. Performance improvements should come with some sort of numbers demonstrating.
Run tests with:
clojure -X:dev:test
...or start a REPL and evaluate at will.
If you have an idea for a new feature, please discuss it before you write any code. Open an issue or drop by #replicant on the Clojurians Slack.
Support symbols for classes.
Fix a bug in the development assert that warns against conditionally including the attribute map.
Use a StringBuilder (JVM) or array (JS) to build strings in replicant.string
for a 3x performance boost in replicant.string/render
.
Fix a bug where development asserts weren't required properly, leading to compiler warnings, and even exceptions during rendering.
First public release.
Can you improve this documentation? These fine people already did:
Christian Johansen, larstvei, Peter Strömberg & Brandon RingeEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close