Replicant Documentation

repository·main·Indexed 19 days ago

https://github.com/cjohansen/replicant

A lightweight, dependency-free data-driven rendering library for Clojure and ClojureScript. Replicant transforms hiccup data into DOM nodes or strings, treating the UI as a pure function of application state. It provides rendering via `replicant.dom/render` and `replicant.string/render` and supports interoperability with Web Components.

Tokens
1.8K
Snippets
9
Records
10
Agent score
18%

What's inside Replicant

  1. Interoperability with Web Components

    main

    While Replicant is designed to be a standalone rendering library and does not recommend integrating with other Virtual DOM frameworks (like React), it interoperates well with Web Components. You can render custom elements by using their tag names in your hiccup data.

    [: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"]
    ]
  2. How Replicant's rendering model works

    main

    Replicant follows a pure functional UI model: State (data) in, hiccup (data) out.

    Instead of managing local component state, subscriptions, or networking, you treat your entire user interface as a pure function of your application state. When state changes, you re-run your function to produce a new hiccup tree, and Replicant efficiently reconciles the DOM to match that tree.

    Replicant is strictly a rendering library; it does not include state management, async rendering, or networking utilities.

  3. Run the Replicant benchmark and generate reports

    main

    After building Replicant and the test runner, you can execute the benchmark from the root directory.

    Standard Benchmark Workflow

    1. Run the benchmark for Replicant (takes ~5 minutes, Chrome will open/close multiple times): npm run bench keyed/replicant
    2. Generate the results report: cd webdriver-ts && npm run results
    3. View the report at: http://localhost:8080/webdriver-ts-results/dist/index.html

    All-in-one Headless Workflow

    To run the benchmark, validation, and report generation in a single headless process, use: npm run rebuild-ci keyed/replicant

    # Run the benchmark
    npm run bench keyed/replicant
    
    # Generate results
    cd webdriver-ts
    npm run results
    
    # Or use the all-in-one headless command
    npm run rebuild-ci keyed/replicant
  4. Compile the test runner and build Replicant

    main

    Before running a benchmark, you must compile the WebDriver TypeScript runner and build the production version of Replicant.

    1. Compile the test runner: Navigate to webdriver-ts, install dependencies, and run the compile command.
    2. Build Replicant: Navigate to frameworks/keyed/replicant and run the production build command.

    Once built, you can manually verify the Replicant build by visiting http://localhost:8080/frameworks/keyed/replicant/ in your browser.

    # Compile the test runner
    cd webdriver-ts
    npm ci
    npm run compile
    
    # Build Replicant
    cd frameworks/keyed/replicant
    npm run build-prod
  5. Set up the js-framework-benchmark environment

    main

    To run benchmarks, you must first set up the js-framework-benchmark repository and its server. Follow these steps in order:

    1. Clone and enter the benchmark repository.
    2. Install dependencies using npm ci.
    3. Run the server installation script.
    4. Start the server.

    Keep the server running in the background while performing other steps.

    git checkout https://github.com/cjohansen/js-framework-benchmark.git
    cd js-framework-benchmark
    npm ci
    npm run install-server
    npm start
  6. Benchmark experimental changes to Replicant

    main

    When optimizing Replicant, use a copy of the framework directory to avoid overwriting the main build. This allows you to use the directory name as a unique key in the benchmark report.

    Workflow for testing changes

    1. Copy the Replicant directory to a new name (e.g., replicant-head).
    2. Copy your modified source code into the new directory's src folder.
    3. Run the benchmark using the new directory key.

    Fast validation

    To avoid running a full 5-minute benchmark on code that might be broken, use the isKeyed command with the --headless true flag for faster feedback: npm run isKeyed -- --headless true keyed/replicant-xyz

    # Copy and test a modified version
    cp -r frameworks/keyed/replicant frameworks/keyed/replicant-head
    cd frameworks/keyed/replicant-head
    cp -r ~/projects/replicant/src/replicant src/.
    cd ../../../
    npm run bench keyed/replicant-head
    npm run results
    
    # Fast validation for broken code
    npm run isKeyed -- --headless true keyed/replicant-xyz
  7. Compare Replicant against other frameworks

    main

    To compare Replicant's performance against other frameworks (like React, Reagent, or VanillaJS), build the target framework and run the benchmark using its directory key.

    Example for React:

    1. Build the framework: cd frameworks/keyed/react && npm run build-prod
    2. Run benchmark: cd ../.. && npm run bench keyed/react
    cd frameworks/keyed/react
    npm run build-prod
    cd ../..
    npm run bench keyed/react
  8. Render hiccup to the DOM

    main

    Use replicant.dom/render to render hiccup data directly into a DOM node. This is the primary way to manage your UI: express your entire UI as a pure function of your application state, and call render whenever the state changes to efficiently update the DOM.

    (require '[replicant.dom :as r])
    
    (r/render js/document.body
      [:div.media
       [:aside.media-thumb
        [:img.rounded-lg {:src "/images/christian.jpg"}]]
       [:main.grow
        [:h2.font-bold "Christian Johansen"]
        [:p "Just wrote some documentation for Replicant."]
        [:p.opacity-50
         "Posted February 26th 2025"]]])
  9. Render hiccup to a string

    main

    Use replicant.string/render to convert hiccup data into a string. This can be used on both the client (JavaScript) and the JVM.

    (require '[replicant.string :as s])
    
    (s/render
      [:div.media
       [:aside.media-thumb
        [:img.rounded-lg {:src "/images/christian.jpg"}]]
       [:main.grow
        [:h2.font-bold "Christian Johansen"]
        [:p "Just wrote some documentation for Replicant."]
        [:p.opacity-50
         "Posted February 26th 2025"]]])