Why Not Mithril?

This small framework is quite capable

November 21, 2018
javascript frontend web

Opening Image

We’ve all been there: a small part of your traditional web app could really use some SPA-like interactivity. You could slap it together with jQuery, but dealing with updating all elements reliably could get messy. A reactive framework may work better in this case, but there can be a lot of baggage with something like React or Vue; you just want this ONE thing to be a bit fancier after all.

If you find yourself in this place, Mithril is worth checking out.

Mithril bills itself as “a modern client-side Javascript framework for building Single Page Applications”, and backs it up with things like a router and a request handler out of the box. Despite its full-featuredness, it works just as well for single components, and it comes in at just 22k minimized, which is less than a quarter of React’s size.

To better describe Mithril, I think it may help to compare and contrast it with React and Vue.

Similar to React

  • Must be mounted at a specific element, operating only within it
  • Use Javascript logic to control rendering

Different from React

  • Operating on global state is simple
  • Easy without compiler / transpiler

Similar to Vue

  • Geared more for enhancements to traditional web apps
  • Setup is simple

Different from Vue

  • All logic expressed through Javascript
  • Does not operate over server-templated HTML

To give an idea what a simple component might look like, here’s a slap-dash example:

// todo.js

var root = document.getElementById('root');
var newTodo = '';
var todos = [];

function setNewTodo(value) {
  newTodo = value;
}

function removeTodo(i) {
  todos.splice(i, 1);
}

function addTodo(value) {
  todos.push(value);
  newTodo = '';
}

var TodoComponent = {
  view: function() {
    return m('div', [
      m('ul', todos.map(function(todo, i) {
        return m('li', [
          m('span', todo),
          m('strong', { href: '#', onclick: function() { removeTodo(i) } }, ' X'),
        ]);
      })),
      m('input', { value: newTodo, oninput: m.withAttr('value', setNewTodo) }),
      m('button', { onclick: function() { addTodo(newTodo) } }, 'Add Todo'),
    ]);
  }
};

m.mount(root, TodoComponent);

And here’s the example in action.

The main thing that may stand out is the use of the m function. m has many different forms in terms of the arguments it receives, but a general form is: m(<tag or component>, <properties>, <children or textcontent>). The properties portion can be elided in place of the children. The children don’t even have to be an array, and can be written as additional arguments.

The docs cover the function’s flexibility and pretty much everything else, including common scenarios and a few gotchas.


For me, the main benefits of Mithril have been:

  • Easier to manage display logic than jQuery
  • Easier to set up than React
  • Better fit for isolated, specialized components than Vue

Each of the frameworks have their place, but Mithril hits a certain sweet spot. Hopeully I’ve convinced you it may be worth adding to your toolbelt.