
React vs Mithril
Goal
React is a very popular and feature-rich web frontend library, maintained by Facebook, for building modern Javascript web interfaces. Mithril is another simliar lesser-known library, claiming to produce smaller bundles with high performance. The goal here is to build a pair of simple skeleton web applications using each of the frameworks, compare the development process and products, and examine the possibility of using Mithril for some use cases.
I'll compare some differences in the source code, then compare build time and bundle size for both development and production.
Development tools
To keep the comparison fair, the two apps should use similar tooling, JSX components, and produce the same HTML and CSS. I'll set up both versions of the app as similarly as possible using webpack to build static bundles. Tailwind is included as a css framework since it supports pruning, but CSS will be bundled into a separate file and shouldn't affect the js bundle. Both versions are available as a Github Repo.
Code Differences
The major difference is implementing components. React components can be functions, while Mithril components are Javascript Objects with a view method.
Mithril requires a little extra babel configuration to use JSX. Without JSX, Mithril uses the m(...) function to define DOM elements. The @babel/plugin-transform-react-jsx transforms JSX into calls to m(...).
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-react-jsx", {
"pragma": "m",
"pragmaFrag": "'['"
}]
]
}
Example React Component
The following is an example of a very basic Layout component using React. Note that children is a special component prop that contains the nested children within the JSX tags of <Layout>.
import React from 'react';
import Header from './header';
import Footer from './footer';
const Layout = ({children}) => (
<div class="flex flex-col h-screen">
<Header />
<main class="p-4 flex-grow">{children}</main>
<Footer />
</div>
);
export default Layout;
Example Mithril Component
The same Layout component in Mithril returns an object whos view method is the same as the React version of the Layout component.
import m from 'mithril';
import Header from './header';
import Footer from './footer';
const Layout = () => {
return {
view: ({children}) => (
<div class="flex flex-col h-screen">
<Header />
<main class="p-4 flex-grow">{children}</main>
<Footer />
</div>
)
}
}
export default Layout;
Build Comparison
The following table compares very basic web applications that produce the same output using the two frontend frameworks under test. Bundle sizes only include production javascript. Build time includes transpiling and CSS compilation/purging, even though the CSS output should be the same for both methods. These were all measured on the same machine and are CPU dependent, so your results will likely vary.
| Benchmark | React Skeleton | Mithril Skeleton |
|---|---|---|
| dev build time | 2.40 seconds | 10.23 seconds |
| dev bundle | 2617 K | 237 K |
| production build time | 5.24 seconds | 8.22 seconds |
| production bundle | 131 K | 30.0 K |
| production bundle (gzipped) | 42.7 K | 10.8 K |
Use Cases
React is a well-maintained, widely-adopted framework that transpiles quickly to reasonably sized bundles. For large or constantly updating projects, React is likely still the best option. For business applications, most frontend developers will know (or benefit from learning) React.
Mithril's advantages are its small bundle size and render speed, so it would be well suited for very simple Single Page Applications or running under limited space or computation power, such as embedded systems.