Hacker News new | past | comments | ask | show | jobs | submit login
Alternative lightweight UI library to modern day frameworks (mithril.js.org)
137 points by turblety on Jan 16, 2021 | hide | past | favorite | 72 comments



We shipped a very major product (300 person company) on Mithril.js a few years back when React was young and Angular was the go-to in this space.

We had a fairly positive experience, but ran into enough problems here and there with vdom rendering bugs that we eventually decided to rewrite the entire product 4 years later in React.

Certainly, it did was it was supposed to very well, until we really pushed it to its limits with vdoms that were complex and mutating in real time. Then we broke it non deterministically and couldn't reliably reproduce the issues that we were having each time for a solid bug report. Couldn't really even reproduce them consistently in production, they would just happen in random places.


Mithril author here. Curious what version you were using. There have been some notable internal changes to the engine over the years.

The 1.0 release was a complete rewrite of the previous codebase, and included a very aggressive optimization inspired by inferno.js (called node recycling) that turned out to cause issues in some edge cases and didn't materialize significant enough performance benefits given the added internal complexity. I suspect that this is what was causing you grief.

This optimization has since been removed.


Hey Leo,

Yeah we reported a few bugs over the years and many of them got fixed. We were using Mithril 0.x. We did get the product to a point where it was very stable, but there were patterns that we had to avoid (for example, at the time IIRC we had spooky bugs with children cycling between an element, a list of elements, or an empty array []).

In the end, the reason that we moved away from Mithril.js was that as a 300-person company, we just didn't have the resources to give it the attention that we felt we needed to give it (i.e. contribute) vs. the timeline that we needed for isolation and resolution.

Before we built our app in Mithril, I built a MVP prototype in Angular and the performance was so bad that the product was marked as "not plausible". Discovering Mithril.js was the only reason we decided to go through with the project. In some respects, the company owes its market-leading position to Mithril.js whilst its competitors are still crawling out of the dark ages of TTY and desktop thin clients


> We were using Mithril 0.x

Ah, yeah things have improved a lot since the 0.x days.

> I built a MVP prototype in Angular and the performance was so bad

I hear you. Having issues with Angular.js performance at work was the reason I started Mithril.js.

It's always interesting to hear war stories :)


I have been using Mithril.js for a while and never ran into problems, but admittedly I only used it for small, personal project.

What I liked about Mithril was its simplicity: a clean API with a handful of methods but batteries-included at the same time, and very easy to learn, too!

Eventually I decided to write my own micro framework which borrows heavily from Mithril in terms of api design and approach (https://h3.js.org) -- basically, like Mithril, it comes with its own Virtual DOM implementation, hyperscript syntax (imho the best way to write a view, once you get used to it), a minimal router but also more obvious ways to manage local and global state.

Yeah, I am not even thinking about competing with React or other frameworks, as long as it works for me. I have learnt more building a micro framework from scratch about how single page application work than from using React or Angular and constantly checking stack overflow and other docs to make sure I was doing stuff "in the right way".

I would however be curious at what are the limits of such frameworks. Real-time dom updates... depends how complex I guess, and how fast. It would be nice to have a way to benchmark this properly...


Any chance you remember what those bugs resulted in? I’m dealing with the same scenario for work where I’m using Mithril and have been wondering if what I’m seeing is due to my usage or the library itself. I do love the library and its community but I’ve run into some crazy ui issues, especially when using keyed nodes, that I’ve never seen with the more mainstream vdom options I’ve worked with.


Mithril contributor here (former maintainer).

I've been out of the loop for a while, I'm getting back to it, and if you've discovered a keyed diff bug I'd love to hear about it.

Feel free to hop into the gitter chat (https://gitter.im/mithriljs/mithril.js) to explore the problem, or to file an issue if you're sure the bug is ours.


I would realy love to know what problems you faced?

Maybe they've been fixed, or are there are genuine scalability problems?


ten years ago I was writing UIs in Qt, given that comment in ten years I'm confident I'll still be writing UIs in Qt


Is it possible to HTML DOM apps in Qt? Is there any blog/book/video that you'd recommend a Qt noob?


The point isn't that you can do web UI in Qt (you can, but it's on a canvas and very rough around the edges), but that web UI frameworks often struggle to achieve a lot of what is just a wave of the hand in desktop frameworks.


The amount of engineering money that web companies spend to have a crappy app ui in the browser is mind-blowing.


Right now Next.js might be the hottest front end framework but I'm looking for something simpler to build SPA's. I'm not interested in SSR or SSG at all. Mithril.js looks very promising as it provides you with everything you might need to build a simple web app out of the box. The only other frameworks that do that is Angular and Ember, but they're both declining in popularity especially Ember. On the other hand React.js has CRA that is very complicated and doesn't even come with routing out of the box. Is there any other good and modern SPA framework out there?


Vue and Svelte are both good. I'm not sure why create-react-app is a problem, but Vue can run without any scaffolding. I think it's worth just accepting that some scaffolding is needed for bundling, transpilation, etc.

There are dozens of alternatives like mithril - small in size, scope and community. You might miss a system for managing state in Mithril, as well as pre-built component libraries like Vuetify or react-bootstrap.


I tried out Svelte recently. I really like the idea of a 'compiler first' framework which offers useful features that compile away to plain old lightweight JavaScript. I got on ok with the bare-bones Svelte compiler, but I found the surrounding ecosystem to be lacking.

There are two different material design libraries for Svelte. [0][1] I wasn't able to get either of them to behave. It looked like they weren't being kept up to date with Svelte, or else the documentation was inadequate.

I then gave Angular a go, and encountered no such issues. Angular has the added bonus that its material design library [2] is very mature and well polished.

[0] https://smeltejs.com/

[1] https://sveltematerialui.com/

[2] https://material.angular.io/


I know Angular seems to not be popular right now, but I am genuinely enjoying my job because of it. Maybe apart from animations, everything seems to consistently work. Even updating major versions is a mere footnote rather than a chore.


> I know Angular seems to not be popular right now

In terms of being in widespread use, I believe Angular is either #1 or #2 (competing against React). It's certainly not a 'cool' choice, it's a boring and stable choice, but there's a lot of value in that.


I've been liking solid-js. It's fast, compact, ergonomic and the people are friendly. https://github.com/ryansolid/solid


I've become a big fan of light weight mostly native web components.

I use lit-html for rendering.

Then I sprinkle in components as I need from things like ionic or shoelace.style


AppRun (https://apprun.js.org) is a very nice JavaScript library for building reliable, high-performance web applications, including SPAs.


It's not clear why there is not more attention paid to apprun...it is a very simple framework/library while being powerful conceptually too.


I think most frameworks take the constellation approach (i.e. separate libs for router, etc). If you're ok with having to install a few extra packages (which isn't all that uncommon these days), pretty much any of them will do the job.

Mithril is sorta unique in taking the more batteries included approach that angular and ember adopt, though it is admittedly far less kitchen-sink-ish


It's not a framework per se, but you can give Mint (www.mint-lang.com) a try :)

It's specially created for SPAs.


I like to chime in every time I see a thread about Mithril. I learned modern SPA development with Mithril and in many ways still prefer it over React or Svelte.

It's definitely starting to show its age as many of the main contributors have moved on and new libs are being created everyday. However the chat [1] is still very active and there are always great discussions going on there that are often not even specifically about Mithril. One of the best dev communities I've found, honestly.

One major benefit of Mithril for me is the lack of need for polyfills while still including a router, XHR utils, and simple state management, AND being compatible with IE11 out of the box, which is invaluable for many government contracts I work on where I don't want to introduce any potentially complicated build tools to an already complex codebase.

[1] https://gitter.im/mithriljs/mithril.js


I love it because you not don't special state management like redux unidirectional flow or mobx observables, or even setState/useState. Just use POJOs and mutate the state however you like, because it automatically redraws on events & xhr so all state changes are picked up on the next render. This typically covers all the cases you need, of course there is a way to prevent or manually trigger a redraw for edge cases.


I used to use mithril for almost every new project I'd start, but I've switched over to using React w/ Hooks for just about everything for two main reasons:

- toolchain support is a lot less finicky and better supported (you can use parcel and it "just works") - should I need to bring in a obnoxious third party library, it's far more likely to exist in a react world than mithril

If you're just building something small / on your own, mithril is definitely worth a shot though, it's relatively pleasant to use and packs in some very handy XHR related helpers


I dunno, I see a lot of react codebases at my day job, and my experience is that libraries are all over the place. The really popular libs are often framework agnostic (e.g. lodash, date-fns, etc), but there's also a long tail of questionable quality libs: some react packages only work with webpack, some use unusual idioms (e.g. having to reference a node_modules path for some css, which doesn't fly with yarn 2), some are unmaintained, etc.

I've also seen cases where people were not aware that high quality vanilla libs exist, e.g. react-dnd vs dragula

There are a lot more wrapper libs for react, that is definitely true, but FWIW, I've come to despise them. Often you end up running into governance/versioning issues (e.g. one moving part releases a new version but you're stuck with the old one because a wrapper author doesn't have time to fix the breaking change, or are MIA, etc), or there are missing/broken pass-through options or whatever...


Hi Leo. Thanks for creating Mithril.

Likewise at work I currently have to deal with React and its challenges. I have previously built other applications in Mithril (and still do in my spare time). I much prefer Mithril and lobbied for its use at work. But sadly React has so much mindshare which was persuasive to management. The only plus to that situation of using React was that I increasingly saw firsthand how much better the developer ergonomics are for Mithril over React -- and eventually wrote the essay about that linked below called "Choose Mithril". :-)

As an example on libraries and React patterns, the emphasis on Redux for React in particular can rapidly create messy bloated codebases that are hard to maintain. That is due to the accidental complexity in React by its premature optimization of requiring use of setState() on components to queue redraws -- which Redux then tries to hide to support global state. Mithril by contrast makes it possible for developers to store state however they want by the brilliance of (by default) just assuming any time the user touches the UI (via anything with an added event handler like for a button press) that the UI needs to be rerendered (unless the developer choose otherwise).

Here's a longer list of reasons why I prefer Mithril to React: https://github.com/pdfernhout/choose-mithril "tl;dr: Choose Mithril whenever you can for JavaScript UI development because Mithril is overall easier to use, understand, debug, refactor, and maintain than most other JavaScript-based UI systems. That ease of use is due to Mithril's design emphasis on appropriate simplicity – including by leveraging the power of JavaScript to define UIs instead of using an adhoc templating system. Mithril helps you focus on the essential complexity of UI development instead of making you struggle with the accidental complexity introduced by problematically-designed tools. Many popular tools emphasize ease-of-use through looking familiar in a few narrow situations instead of emphasizing overall end-to-end simplicity which -- after a short learning curve for Mithril -- leads to greater overall ease-of-use in most situations."

And a key point from the conclusion: "The fact that Leo Horie's Mithril -- a project started by one brilliant, kind, and generous person and now supported by a few volunteers -- can attract as much interest and support as it does relative to Facebook's React and Google's Angular (both backed by millions of dollars of paid development and free publicity) implies a lot about Mithril's technical advantages and developer ergonomics."

As another example, over the winter vacation, I helped my kid make an interface in Mithril+HyperScript+Tachyons as a graphical memory monitor for Windows with a simple Node.js backend. He had essentially never used JavaScript before but had previous used Lua for game scripting, C++ for the Arduino, and a bit of Java for Minecraft. And while he still would have a lot to learn about HTML/CSS/JavaScript to do Web UI stuff entirely on his own, now at least he knows he could build more such interfaces -- including for embedded devices. Mithril+HyperScript+Tachyons essentially just was so easy to use and explain that it got out of the way -- and so almost all our time was spent discussing JavaScript issues, and the application design, and other libraries the application needed. That ease of learning Mithril shows how it is a mistake for management to choose React on the assumption that they need to pick the most popular platform to have the easiest hiring of developers. Mithril's short learning curve means even if you need to hire UI developers who have never used Mithril, any reasonably competent developer can get up to speed quickly.

In short, Mithril+HyperScript+Tachyons(OrOtherAtomicCSS) is an awesome combination that is much more fun to develop in than React.

You rock, Leo!!! Thanks again for making the programming world a better place.


Hooks were what made me choose React to migrate to from AngularJS at work. I really like the concept of (state) => ui, but had no interest in react’s former class-based API. It was too complex. With hooks, I can write code in a more functional style, and even though they’re a little weird I think it results in more maintainable code.

I really wanted to push for using Reagent in Clojurescript, or something like re-frame that uses it, since CLJS has much better enforcement of and support for immutability-by-default and function composition. Everything that custom hooks do is handled by plain CLJS functions. It feels closer to meeting the design goals of React than React itself does, even with hooks.

It’s a hard sell though when I’m the only one at the company who knows the language. Maybe someday...


If you want to try mithril in a mid-sized project, sure do it, cause it is a nice, free as in freedom library to render vdoms without imposed opinion on how to manage state. But be aware that it has no error handling around view() method and any error thrown from there will irreversibly break mithril internals everywhere on the page, this is by design. Second thing, I didn’t push it to the limit as another commenter, but massive vdoms (many tens of thousands of vnodes) are slow to even rebuild and compare, so you’ll have to use lazy techniques described in docs. It is not exclusive to mithril, but worth knowing. Otherwise, mithril is basically a core vdom tech similar to vue and/or react, wish these two had their render cycles as separate packages. Also, if someone knows a cheap way to turn react into mithril’s spirit, e.g. via light setState-detaching layer, please share.


> but massive vdoms (many tens of thousands of vnodes) are slow to even rebuild and compare

Sounds like a terrible user experiance? Would you mind educating me on an appropriate scenario where you may need tens of thousands of vnodes?

Maybe large unpaginated tables? A chat panel where you have scrolled through a large history?

Even if a framework like React can handle that many nodes, surely there must be better ways of handling the requirement. I'm not sure a user can actually consume tens of thousands of dom nodes.


It was a master-detail “form”, rich-formatted financial records in the left pane and svg-heavy graphs for attributing records to edges on the right. Already heavily filtered on both sides, and required to be navigatable without constantly changing subfilters.

Estimating, every left row could consist of 15-20 vnodes and every graph of around 50+ min. I think I’ve seen 12-15k vnodes on average day, depending on how much data remained unmanaged and how structured the right side was in the middle of experiments.

surely there must be better ways of handling the requirement. I'm not sure a user can actually consume tens of thousands of dom nodes.

We tried windowing the data, but that simply moved delays to operators. They don’t consume it all at once, but they have to detect groups by using “natural intelligence”. The fixed process that spans multiple entities and liabilities wouldn’t allow to automate it further. Sometimes it’s what it is, welcome to real world business complications. As I said, it’s not mithril’s fault at all, but something to consider if you have to.


Humongous DOMs eventually stop scaling even without any javascript on the page (e.g. look at how long it takes to load the ecmascript spec), so it's definitely important to account for DOM size early in design.

With that said, for mithril specifically, there are a few different techniques that I've heard people use to avoid overly slow diff times:

- design changes (search, filtering, pagination, etc)

- occlusion culling (basically render only list items that are actually visible on screen)

- islands (basically mount a sub-app onto a vnode.dom so that it renders independently without forcing a rerender of the parent app; this takes advantage of the idea that data-down, events-up is a pattern that works across sub-app boundaries)


occlusion culling

Yes, good old model-(controller implements datasource)-view-cellview from any native toolkit. Sadly, to implement that in html, which doesn't have any primitives for it, means that you have to combat both NSScrollView/GtkScrolledWindow from scratch and html/css complexity. That alone is a project much bigger than some enterprise fintech toy I'll ever dare to approach. Maybe some day web will reinvent native cells and cell-rendering containers, who knows.

islands

Hmm, this sounds interesting, thanks for the cue!


Agreed. Charts and large SVGs, etc are generally best rendered independent of the vdom. I’ve seen React and Preact both crawl under similar setups, so this isn’t a knock on Mithril, albeit it does appear that Mithril is a bit slower than Preact with large diffs.


For large immutable DOM trees like CSS-stylable SVG graphics, I've seen people use m.trust, which makes the diff of the entire SVG tree as cheap as a single string comparison.

For complex charts, I think deferring to something like d3 might make more sense than a vdom based implementation since d3 provides better domain-specific APIs.


Sounds like a good usecase for some framework without vdom like Svelte.


Svelte + TS has been very enjoyable for my side project thus far, and I’m more of a systems/compiler dev than any sort of webdev.


I work on such doms regularly. A virtually paginated tablewould render around 100 rows. 20 columns means rendering 2K vnodes for the plainest of cells. If a few of those columns render small charts it can easily add upto 100k.


> similar to vue and/or react, wish these two had their render cycles as separate packages

Not sure if it’s exactly what you’re looking for, but Vue 3 separates its core into independent modules that you can use outside of Vue if you want to.


Mithril is the React Facebook would have written if its devs didn't have too much time on their hands - it's wonderfully simple.

I stole their API somewhat for my 33-line-React, if you have any interest in how stuff works under the hood - check it out! https://leontrolski.github.io/33-line-react.html


Just in case someone interested.

Mithril works as it is in Sciter.JS

Yet this:

    JSX = m;   // let's  use Mithril as a driver of JSX expressions
enables built-in and native Sciter's JSX extension to work with Mithril:

See demo: https://github.com/c-smile/sciter-js-sdk/blob/main/samples/m...

Sciter.JS uses QuickJS with JSX parsing extension added : https://github.com/c-smile/quickjspp/blob/master/quickjs-jsx... . It is significantly easier and effective to add JSX as part of native JS parser rather than to have monstrous JS-parser-in-JS infrastructure of Babel.


I have noticed newer generations of developers believe they need heavy frameworks like React to develop web applications. Most apps don't need such heavy frameworks. Here's a 500-line "framework" (if you can call it that) https://github.com/Rajeev-K/mvc-router and here's an example app built using it: https://github.com/Rajeev-K/eureka For templates I used https://github.com/wisercoder/uibuilder which is a 200-line lib. This is about as "close to the metal" as you can get, and still be productive.


"Close to the metal" should not be used to talk about javascript ... I love js ... But let's be realistic, vanilla js is great but very far from metal


I like "bare plastic JavaScript" :-)


By "metal" I meant the browser, so avoiding heavy libs.


I’ve never used Mithril but in looking over this it seems very similar to a small library I wrote myself, especially with regards to routing and the use of # in the URI. I think solutions to certain problems are universal and the way we implement those solutions is the interesting part. Of course my library was never optimized for large-scale DOM mutations or other such real-world issues, but it’s always fascinating to see someone develop similar solutions. So why did I even write my own library? It was more out of curiosity than need. I also like to understand how “magical” things work, and for me, the best way to understand something is to try to do it myself, even if I don’t end up fully completing whatever “it” is. Discovery is a powerful benefit that I feel modern software engineering doesn’t provide as much as it used to.


I was an avid user of Mithril several years ago and even connected with one of the maintainers on LinkedIn. However, I ran into issues (I forget what they were at this point) building v1 of my social network and eventually found Svelte.

Mithril still has a place in my heart though, it was a joy to use.


Mithril is really special among JS frameworks. It has a very tiny API and thus the resulting components are powerful and highly reusable. I think of them as Lego bricks to build worlds inside browsers. Whenever the architects or product owners come up with an idea never seen before I prototype using Mithril, because all other tend to fail involving of unexpected amount of complexity. Mithril gives you all degrees of freedom and surprisingly often that's considered a disadvantage.

Did I mention it's fast?


I’d like to use a simple front end library that doesn’t use a vdom, doesn’t require a special state system, doesn’t require special compilation, is performant, and largely gets out of my way.

I currently use Preact and am pretty happy with it, even though it doesn’t check most of those boxes. Is there something that does?

Anyway, Mithril looks nice. I’ve kicked the tires a few times, but comments like the ones here in this thread have prevented me from adopting it.


There's Svelte, that matches most of your requirements, but unfortunately does require a compilation step.

Since I'm a backend dev, I've been looking for a straight-forward library to use for my next project and found this. I haven't yet used it on a project though

https://svelte.dev/


Svelte with Snowpack does compilation in milliseconds.


How long does compilation typically take?


"Alpine.js offers you the reactive and declarative nature of big frameworks like Vue or React at a much lower cost. You get to keep your DOM, and sprinkle in behavior as you see fit... Alpine doesn't use a virtual DOM. This implementation allows Alpine to stay rugged and use the real DOM to work its magic" https://github.com/alpinejs/alpine


I’ve seen Alpine, and it is interesting, but another bullet point in my wish list is vanilla JS; no new template language. JSX is just a small bit of sugar on top of vanilla JS, in my mind, so it is acceptable.


From the brief glance I've taken at Alpine I didn't think it did have a template language - unless you refer to it's use of custom html attributes?


Alpine has directives like x-if and x-for. For a lightweight templating library I would recommend https://pure-js.com. It's been around for ages. The PureJS directives take some time to get used to, but are quite powerful once you do.


LitElement checks all those boxes: https://lit-element.polymer-project.org/


The “special compilation” step is what annoys me as well. Modern JavaScript is powerful enough and almost universally supported enough to no longer need this. I’m looking forward to the day when we don’t have to use transpiled languages and preprocessrs for basic things.



The modern equivalent to mithril.js would be Hyperapp + Parcel for me. Easy to get started, with enough batteries included.


From the Framework comparison page: "Guild Wars 2 uses Mithril (yes, inside the game!)"

I would love to hear more about that! Anyone know where I can find more information?


I read an interview by Pat Cavit (the former UI lead at ArenaNet) where he briefly speaks about it here: https://carlmungazi.github.io/sourcecodeadventures/posts/pat...


Does Mithril include state management? I see it’s being compared to Vue + VueX but I didn’t see other mentions of state management on the linked page.


I've only just learned about Mithril streams: https://mithril.js.org/stream.html#combining-streams

No experience of using them, but they look cool for managing state.


It’s left up to you. POJOs work just fine in Mithril, but you can use any of the existing libraries (Redux, Mobx, etc) too if you want.


So then it’s probably more fair to compare it to Vue without VueX included, no?


I wrote a brief blog post[1] about vanilla state management in Mithril. Since Mithril triggers redraws on event handler calls, as another user said, you can just use POJOs very easily.

[1] [link redacted]


You have a very nice-looking blog.


Thanks!


What does modern mean in this context?


By modern, in the context of web development, I generally mean bloaty unnessesary mess.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: