Liking cljdoc? Tell your friends :D
Moira

Moira

Clojars Project Test Status

Modular frontend applications in ClojureScript.

The most fundamental problem in computer science is problem decomposition: how to take a complex problem and divide it up into pieces that can be solved independently.

― John Ousterhout, A Philosophy of Software Design

What is Moira?

As frontend applications become larger and more complex, or when multiple teams need to work on different features simultaneously, it becomes necessary to structure and organize the code in a way that allows for independent development, maintenance, and deployment of distinct units. Moira is a library designed to accomplish just that based on three core principles.

  • Modular: Manage complexity and limit cognitive load by separating concerns into encapsulated units with well-defined boundaries and explicit contracts
  • Event-driven: Reduce coupling between parts of the system through dependency injection and a central event log
  • Adaptable: Optimize for flexibility by embracing the dynamic nature of ClojureScript and the browser environment

What Moira is not

Unlike Reagent or UIx, Moira is not yet another ClojureScript React React wrapper. It does not directly interact with the render cycle, and there is no preference on which UI library to use for component building and instrumentation.

Moira is not intended to be a complete framework for building web-based applications like re-frame or Fulcro. Moira's event system and application state complement UI events and UI state management, rather than replacing them.

That being said, the all-state-in-one-place philosophy of re-frame's global application state does not play well with Moira's main objective of creating self-sufficient components for managing encapsulated module state independently.

Usage

Add Moira to your project dependencies:

{:deps
 {io.github.pitch-io/moira {:mvn/version "v0.8.0-alpha"}}}

Configure and start a system for bootstrapping your application:

;; configure modules and dependencies
(def system {:router {:start #'router/start}
             :session {:export #'session-manager/export
                       :start #'session-manager/start}
             :ui {:deps #{:session}
                  :resume #'ui/hot-reload
                  :start #'ui/start
                  :state {:el (.getElementById js/document "app")}}})

;; create application instance
(defonce app (application/create system))

;; bootstrap application
(defn ^:export init []
  (application/start! app))

;; instrument hot reload
(defn ^:dev/before-load stop []
  (application/pause! app))

(defn ^:dev/after-load start []
  (application/resume! app))

Contribution

Prerequisites

Development

To set up the project (e.g., install npm dependencies), execute the init task once:

bb init

Starting an environment for interactive development, you can serve an in-browser test runner at http://localhost:8031 and have everything recompiled automatically on any change with:

bb test:browser

You will then be able to connect to the app via nrepl on the port returned by:

cat .shadow-cljs/nrepl.port

Learn about all available tasks with:

bb tasks

Testing

For a single execution of the test suite in headless mode, invoke:

bb test:once

It is also possible to automatically recompile and run the headless test suite on changes:

bb test:watch

Release

Update CHANGELOG and README. Commit changes.

git commit -a -m "Prepare release."

Tag commit with the new version and description. Push tagged commit.

git tag -a v0.1.0 -m "First release."
git push --follow-tags

Check version and publish release on Clojars.

bb release:version
CLOJARS_USERNAME=username CLOJARS_PASSWORD=clojars-token bb release:publish

Published under the MIT License.

Copyright © 2021-2023 Pitch Software GmbH

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close