Mercury: A Modular Front-end Framework

2015-01-15 00:00:00 +0000 by Alex R. Young

Michael J. Ryan alerted me to a front-end framework called mercury. It's written by Raynos (Jake Verbaten) who has created several useful JavaScript libraries, but mercury seems to have got lots of interest (it's almost at 1000 stars on GitHub).

You can find it at Raynos/mercury on GitHub (License: MIT, npm: mercury). I think you'll like it because it's definitely a modern JavaScript programmer's client-side framework. It has some things in common with React -- the virtual DOM, state management, and render methods -- but the big difference is you can almost completely forget about the DOM. It has a streamlined markup API, so there are no tags mixed in with JavaScript.

It's still small, though, and it plays well with other libraries. The readme has examples that show mercury alongside Backbone and JSX. There are some demos as well that include things like todomvc. Here's the basic example from the readme:

'use strict';

var document = require('global/document');
var hg = require('mercury');
var h = require('mercury').h;

function App() {
  return hg.state({
    value: hg.value(0),
    channels: {
      clicks: incrementCounter

function incrementCounter(state) {
  state.value.set(state.value() + 1);

App.render = function render(state) {
  return h('div.counter', [
    'The state ', h('code', 'clickCount'),
    ' has value: ' + state.value + '.', h('input.button', {
      type: 'button',
      value: 'Click me!',
      'ev-click': hg.send(state.channels.clicks)

hg.app(document.body, App(), App.render);

Mercury encourages immutable state, so the render methods are pure in that they take state and generate markup. However, some of mercury's features are not immutable. Widgets are more complex and allow low-level DOM manipulation.

This idea of mixing functional and imperative programming techniques reminds me of Clojure, and perhaps even how F# feels less "pure" than Haskell because it has to interface with .NET. Raynos identifies the mixed-paradigm approach in the documentation:

Mercury is also a hybrid of functional and imperative, the rendering logic is functional but the updating logic has an imperative updating interface (backed by a stream of immutable objects under the hood).

If you want to read more about mercury, the documentation is split into several Markdown files that you can view on GitHub: mercury/docs/introduction.md. There's nothing specifically Node-centric about mercury, but because it can be installed with npm and is made of small CommonJS modules then it feels like it would work well for Browserify/CommonJS projects.