Show HN: My new JavaScript MVC framework
lhorie.github.io
lhorie.github.io
This is the reason why I like Backbone.JS instead of Angular. The reason why I like Go instead of Java.
Mithril looks really promising! Don't let feature creep turn it into a behemoth! Keep it lean and mean, and excel at the one thing it was made to do!
A few, simple, fresh ingredients prepared quickly and correctly can be much more amazing than a complicated 20 ingredient recipe that takes 2 hours to prepare.
The cycle makes sense. A new programmer finds everything overwhelming, and the simplifications offered by something like Mithril often aren't enough to mitigate that feeling in any meaningful way. It's going to feel like you're drinking from a fire hydrant no matter what.
But as you get a much firmer grasp on the fundamentals, you also gain a much finer perception of bloat and cruft and what's necessary and what's not. So you feel a push to eliminate large all-encompassing libraries, because for the first time you realize that some sort of omniscience is within reach.
Backbone vs Angular? Backbone (without 10 other plugins) is just a small handful of prototypes so you will need to write huge parts of the actual application framework yourself (NIH syndrome). Not really comparable to a fullblown framework like Angular or Ember where you learn their workflow to take advantage of all the features and to save 'technical' time to write more 'business' logic. So again apples and oranges in this case until you mention Thorax and that kind.
@stronglikedan: I don't have plans for extending the core (in fact, keeping it small and modular is a major focus point for me). I do have a list of things I want to tackle next (see the roadmap page), but I'll most likely release them separately from core.
@hcho: re: integrating w/ jQuery: see the integrating w/ other libraries page in the guide section. There's a simple example w/ select2 there.
@abjorn: those are excellent points. Re: turing completeness: my take is that things like good error messages in the view layer are more important than trying to prevent people from doing stupid things (that's what code reviews are for). Re: Bindings: I'm most familiar w/ Angular ones and yes, their bidi-bindings are really convenient, but they fail in some 5-10% of the use cases for me (either by being too aggressive or not expressive enough). So, that's a conciseness vs power trade-off in design from my personal experience. Re: templating, you can take the model-level utilities and integrate w/ other templating libraries. I do provide some comparisons w/ React and a few other frameworks in the misc section of the guide, as well as design rationales in the main guide page. TL;DR I use other frameworks full-time and I've done homework before I settled on the current implementation :)
@hanburglar I do provide a tool to convert HTML to Mithril (although not automated yet), see the "useful tools" page.
@timmiwil: you're right, jQuery is not MVC (I mention this in the comparisons page). The point is that with idiomatic jQuery, the app developer is responsible for knowing when to use .text() instead of .html(), whereas with, say, idiomatic Angular, that's not a concern, ever. jQuery "templating" tends to get pretty hard to audit as widgets become more complex (see select2 source code, for example)
@tzaman: I do contribute to Angular and other projects that I use as time permits (mostly bug reports)
@BaconJuice: it's a side project, but a scratch-an-itch one that I work on pretty much every night. Planning on continuing work on it for the foreseable future. I'm also considering introducing it at my day job as well.
@all: thank you for the feedback, I really appreciate :)
Well, thanks for the framework :)
Apparently, you missed my (now deleted) question:
> It would be nice if you could document the browser requirements.
We're even, since I had missed the answer, which lies at the very end of the misc section of the documentation:
> Mithril allows developers to support browsers all the way back to IE6 and Blackberry.
Wow! This should IMO be on the home page.
---- ---- ----
Edit: Is it possible, for SEO, to load Mithril with a pre-rendered page and have it take over like React?Agreed! I'm in!
As I said, Angular and Backbone use jQuery. So you're just comparing how you've used jQuery (as if that's how any jQuery user would do it) to how they've used jQuery. There is no such thing as "idiomatic" jQuery templating. There are only plugins and libraries that use jQuery to do templating. In fact, what you've done in the jQuery rendering test is incredibly bad practice and is greatly discouraged in the jQuery community. Again, your tests don't make sense.
If you need me to explicate my pointer further, the jQuery "security test" is you asking jQuery to do something stupid and it following orders. It's absurd. You might as well add a native test saying that document.documentElement.innerHTML = "a\"><img src=\"javascript:;\" onerror=\"alert('alert box should not appear')\">"; has a security hole. How dare the browser do what I said!
Stop comparing jQuery to MVC frameworks.
The technical implementation of the jQuery test is flawed on purpose, and that's the point. People make mistakes, some don't know better.
Are you arguing that every jQuery dev team in the world audits their code for stuff like:
- bla.text(firstName + " " + lastName)
+ bla.html(firstName + " " + lastName) // bug fix 1234: make name not wrap
Or that somehow the jQuery community is gonna catch that in your application? Or that your innerHTML example (given a user-defined string) does not have a security hole? That you're gonna find that commit from the junior guy at 3am at crunch time? That "the developer should know better" is a good security strategy? Are you saying that one API that makes it hard to make mistakes not comparable to one that makes it easy to? That's the absurd claim, imho.Like it or not, jQuery is the big elephant in the room, so yes, I'm going to compare to it, to the extent where it makes sense. Is it an apples to apples comparison? No. Neither is the comparison w/ React. But those comparisons are useful to some people, so I provide them.
Nobody's using jQuery only to build large single page apps,that's not true. Comparing jQuery which a DOM manipulation library to any framework that manage the application lifecycle is dishonest.
It would be like comparing underscore to AngularJS,makes no sense.
Back to the point, jQuery and Mithril are more similar than your analogy tries to make it sound. jQuery does AJAX/CORS and Deferreds and .data() and a whole lot of non-DOM stuff that people use when building their apps. There's some stuff that doesn't map like jQuery animations not having a Mithril counterpart or Mithril routing not having a jQuery-core counterpart, but that's cherrypicking the stuff that is different and saying "look, they're different!", while ignoring the similar, comparable aspects.
Also, I'm not sure how familiar you are w/ underscore or Angular, but both have a templating system and utilities to work with lists of data, so there are definitely points that can be compared. These comparisons are really not at all like comparing something like restangular to hoverIntent, so implying that they're equally imcomparable seems like the dishonest and non-productive argument to me, imho.
Sure, that's a fair point given that my explanation in the homepage is skimpy. I did try my best to word it in a way not to diss jQuery as a project: "if you see an alert box, ensuring security with that framework is more work for you". If you have a better idea on how to phrase this point, I'm open to suggestions.
That said, I really like the project because I'm also a big fan of simplicity. Curious to see if there will be a TodoMVC implementation with Mithril for easier horizontal comparisons of actual code.
todo.view = function(ctrl) { return m("html", [ m("body", [ m("input"), m("button", "Add"), m("table", [ m("tr", [ m("td", [ m("input[type=checkbox]") ]), m("td", "task description"), ]) ]) ]) ]); };
@jsx m
todo.view = function(ctrl) {
return (
<html>
<body>
<input/>
<button>Add</button>
<table>
<tr>
<td><input type="checkbox"/></td>
<td>Desk description</td>
</tr>
</table>
</body>
</html>
);
}todo.view = function(ctrl) { return m("html", [ m("body class='application", [ m("input class='add input input-sm input-md"), m("button class='btn btn-success button-green", "Add"), m("table class='table table-strped table-row", [ m("tr class='tr'", [ m("td", [ m("input[type=checkbox] class='checkbox input input-sm' id=firstName name=firstName") ]), m("td class='td", "task description"), ]) ]) ]) ]); };
I honestly can't tell you what the hell that is supposed to be anymore. Also, you guys are using invalid html for everything. Your example is not going to validate on anything.
> Yes, it would be simplificantly simpler to edit html
> if it wasn't stuck in between two strings
> ...
> m("body class='application", ...
You would put attributes in an object. m("body", {class: "application"}, [ ... ])
Sure, it's no Lisp, but to me it's just Javascript's commas that suck the thunder out of it.Quite neat that you can use it for non-React stuff just by tweaking the pragma comment the JSX transformer requires.
Here's an actual example of a Bootstrap table in a React component using JSX: https://github.com/insin/lifequote/blob/master/src/component...
There's not much display logic in it, so it doesn't exhibit the usual progression I've seen when writing React components so far, in which most display logic happens up-front in a component's render() and often gets moved into another method and called directly from where it's going to go in the structure being returned from render(), so you generally don't end up with huge whacks of JSX in components which are doing more work.
```js / @jsx m.dom */
function m(type, props, children) { // assuming m() looks something like this. return { type: type, props: props, children: children}; } m.render = function(lwDOM){ console.log(lwDOM)}; m.dom = {};
// React hard codes this array so we can do something like this to build the mapping ['a', 'span'].forEach((el) => { m.dom[el] = function(props, ...args) { return m.call(null, el, props, args); } });
m.render( <a href={"google.com"}> <span>hello</span> <span>world</span> </a> ); ```
Also, just FYI, the selector syntax follows CSS rules, so you'd write m("body.application"), not m("body class='application'")
Guys, rule of thumb, architecture === directory names. Performance is an implementation detail.
Frameworks live and die by their APIs. The easier it is to work with, to read and write and reason with, the better it is.
But you know what, this can be easily proved. Someone take a stab at todomvc with this and let me know if it hurt or not.
Looks pretty painful, but I do think adapting JSX could be a pretty painless solution so I don't look at it as a deal breaker. I am still yet to find a javascript templating solution that I don't have at least 1 or 2 issues with.
- I'm not sure why you're doing `return m("#todo-app"), [...]` on line 15 of the view, it looks like a typo
- I would probably have written a keyboard utility function similar to m.withAttr to keep the e.keyCode stuff out of the controller and remove the anonymous function in the view
- I generally prefer inline ternary syntax instead of a if statement at the top for the "clear" button.
- the pluralize snippet can also be pulled out into a utility method
- I also tend to favor this syntax: m("input#new-todo[placeholder='What needs to be done?']") if the value of the attribute is static (line 18)
It's perfectly possible to not have FOUC with traditional template languages like mustache, and I don't think having "turing completeness" in your templates is a good thing. Frameworks like Ember.js have also shown that you don't need to manually write bindings to handle when your models change.
That being said, I do see the advantage gained with the virtual DOM you generate from the templates. I'd be interested to see if it was possible to integrate other templating languages in via plugin.
edit: I just wanted to add that I read through the guide expecting to find yet another half-baked framework but the whole thing seems well thought out and I like the philosophy alluded to in the guide. I'm definitely going to try this for my next mini-project.
So basically XAML?
But while me and my coworker have been trying it out there seem to be quite a few bugs with it, and I'd much rather have it done at runtime (precompiled for production build) then have to translate it from my HTML-based template every time I make a change.
Looks like Javascript IS the Assembly of the Web.
Javascript is a way to manipulate the DOM, no matter whan those nutters who run it on servers say.
So the big example at the end of Mithril would, for us, be something like (we implement binding as a jQuery extension)
$('.display').bind(data);
Where .display selects the root node of the bound UI, and data is our object.
Which is simpler and less code, I think. (Oh and our binding library has jQuery as a dependency, but is sub 3kB minified and gzipped.)
That said, we haven't put our libraries on github yet :-(
We also do not bind by class because that's a really bad idea. (Actually the way we bind is a lot like Angular, but without being a templating language.)
A key design requirement is that the model does not get polluted with special methods and properties to support the binding -- so (for example) if you have nice RESTful services, you can GET, bind, edit, POST/PUT and everything just works. For moderately complex cases we support "decorators" that live "off to the side" (i.e. do not pollute the model). Again, you can stick getters and setters in your model if you want to, you just don't need to.
The advantages are significant. First -- you have to know HTML. Second -- all the code that works on HTML works on HTML.
We use data attributes to make the binding work. The data attributes are a "template language" if you will, but it's not breaking HTML (and if you read our attributes they make sense without much documentation).
it felt like you were giving a smart person a crash course in javascript
wish more apps sturctured their tutorials like this
great job!
One thing: it feels like it's aimed at people who are already competent at javascript
but your tutorial isn't too many steps away from a being solid "javascript for absolute beginners" guide
So would be cool if you made it slightly more beginner friendly, like I'm sure you're losing a lot of engagment and users because they read the first line of your guide and immediately think it's too complicated
"Mithril is a client-side Javascript MVC framework, i.e. it's a tool to make application code divided into a data layer (called "Model"), a UI layer (called View), and a glue layer (called Controller)"
Like I'd suggest adding a VERY simple sentence about why you'd want to use javascript AT ALL
both on the guide and the start page
like if someone landed on your page and they were good at HTML and css but never really programmed, they could probably use your framework to build their first programming project if you made it a little more beginner-friendly
great work! :)
use some punctuation and
not separate your thoughts out on different lines?
Not trying to be mean, this is just hard(er) to read!
astroturfing
AT ALL
If I am iffy on anything, it would be the templating language, but I suppose a React-type HTML syntax could be optionally layered over top without interfering with anything else. And there is something secure about javascript-rendered HTML in that you are much less likely to have unclosed tag issues, etc.
But for me, having experimented with some of the slower performers like angular, performance is a huge draw, and I am willing to write my templates in js if that's what it takes to get it.
You eventually end up writing your own framework of sorts anyway when you take minimal path.
Angular can be quite fast compared to jQuery in an app of substance. It is not constantly reading/writing to the DOM in most cases, which saves a lot on the performance front. It is also a smaller library than jQuery, and you're not naively applying global or complicated selectors. Plugins rewritten to be pure javascript + Angular also can have a much smaller footprint & be more powerful to boot, such as the Angular UI Bootstrap project (5 KB minified & gzipped as opposed to 15-35 KB? I forget Bootstrap's js size) & contains all of the power of Angular to modify your functionality with them & more.
How do you refactor out bloat from a framework without throwing away the framework?
This is my whole point about not using frameworks. They're a siren that WILL eat you in the end.
Of course, if a framework automates a ton of functionality, it'll naturally be inappropriate for certain projects. I wouldn't try to use Angular for an HTML 5 game, for example, though there's a good chance I wouldn't use jQuery either.
I actually did use Angular for an HTML5 game last week as part of a demo for a conference. Admittedly it was a really simple game (tic tac toe), and it did use Polymer as well as angular, as sort of an experiment. But it worked pretty well, and only took about a day and a half to hack together, with realtime multiplayer and chat using socket.io.
Obviously you're going to run into things that Angular is not really ideal for, but we are trying to make it do what it does very, very well, so in the future it should be suitable for pretty much any mobile or desktop app.
---
This sounds like evangelism, which is not my intent, you're absolutely right about what you're saying, but it's true, sometimes a framework works (and saves a ton of time) that you'd otherwise spend hacking together something awful. Hopefully this mithril thing also saves people a ton of time without them having to worry about numerous other issues.
>Stop with the frameworks. Learn Javascript. Learn CSS. Learn HTML.
That's good advice to someone that might be asking about using a framework. But to someone that has written a framework they probably have a pretty good understanding of Javascript already, and if they didn't it will have improved greatly by the time they are done.I don't code in JS. Maybe a few lines once in a while when it pops up. It just seems like an MVC framework is the javascript equivalent of writing your first recursive factorial function.
The fact of the matter is large code bases need to be supported over time by diverse groups of people and frameworks help enforce standards that get people up to speed quickly.
That developer I knew, he has been chronically unemployed for the last 5 years because he lacks the skills to work as part of a team. Great coder though!
The majority of the Web apps is CRUD + a bit of logic. It makes much more sense to use a framework because 1) most of the things are already there 2) easier to maintain for someone from outside 3) and, most importantly, very few developers have skills to create a nice, maintainable design, accompanied with a useful documentation.
Yes, in ideal world, maybe you should be able to stay framework-less (just made that word up) but the world isn't ideal. We have to sacrifice philosophical ideals for the business because that's what pays the living.
In rare cases, when the app is much more than a simple CRUD, it might make sense to ditch frameworks... But it's very, very rare.
I'll add an addendum to my post that frameworks can be the right tool for the job. But 99% of the time they're used the wrong way and for the wrong purpose.
After building/using Composer.js (http://lyonbros.github.io/composer.js/) extensively I inevitably end up reimplementing parts of it on projects that don't use it because it makes some things so easy.
That said, if you're learning javascript, stay away from frameworks at all costs.
Your view is limiting
>Things like jQuery, underscore, etc...
Sounds great until you have a team of 5 developers maintaining at least a semi-huge code base over the course of some years. Some people leave, new join the team.
Then you really start appreciating frameworks if only for their conventions to structure the code. Top coders can write web apps with jQuery and underscore alone, but everyone else is better off following some conventions.
If your code degrade over time, sorry to tell you, a framework won't solve the problem.
If you have coders that don't care about maintainability of code correction, code organization in whatever technology, they won't care about what you wish.
As usual, they won't take the time to learn the frameworks, will diverge, and you are back to square one with no code that can be salvaged or reused. (at least with vanilla techs you may salvage stuffs)
I think you use frameworks to solve the wrong problems here: you are probably the problem by trying to ditch the lack of real engineering skills in IT (not the letter of engineering. The spirit: making things that are correctly built and are reliable over time... like a plane).
This is all nice and well in academics and start-ups but some years down the road, your code is going to be a mess. Frameworks, especially opinionated frameworks are a tremendous help. Coding in jQuery or native JS without some prodding is at best an accident waiting to happen.
Cheers.
I really like dform's flexibility. I have been able to add every HTML elements that I've needed with the same syntax for every one, making it very simple to stick them into PHP loops to generate the elements based on the query results. I've learned a lot about writing jQuery functions while using it.
FusionCharts is very specific in what it does, and is compatible with many languages. I have actually learned to use it's classes in both PHP and JavaScript so that I can create any part of the chart I please in either language, and it is capable of transmitting data in both JSON and XML even though it uses XML internally. I've briefly taught myself the differences between the formats and have gone from manually creating XML, to learning that JSON is way better, to automatically converting my arrays into JSON data.
I feel that I've kept my project quite lean indeed, and was actually worried about not accomplishing a lot, not being complex enough. But I have intentionally been trying to avoid complexities so that I can make it easy to pick up and use, just include jquery, dform, and the FusionCharts.js/.php (and source code).
I love the simplicity and independent direction this micro-framework provides. It's very 'non-magical' which I think makes it far more appealing.
If you end up solving the HATEOAS/ember-data sideloading/'embedded foreign key data loading' problem I think this will be my goto library (though this probably falls out of the microframework requirements also ;)
uses POJOs; has just enough 'binding'; uses routing and basic promise/A+ implementation.
I'd say this is good and as high level as one should go if they want to churn really good performance out of an app.
Keep it coming mate, and link with me on Twitter. I used a number of micro frameworks and my own glue to make my own mini-framework using much of the same concepts, only I used a templating engine called doT instead of declaring my HTML structure in JS (although I know it is easily possible to generate view code with a tool/script with HTML as input).
@matthiasak mkeas dot org
That strength is also a weakness though. Particularly because for coffeescript (or my favourite, the related LiveScript) it doesn't result in the super-cute syntax of e.g. TeaCup[1][2].
[1] https://github.com/goodeggs/teacup
[2] Markaby begat CoffeeKup begat CoffeeCup and DryKup which begat Teacup
I'm a backend guy beginning to venture into front-end stuff (recently picked up JS for a Node project at work), and the extensive documentation is incredibly helpful for newcomers like myself.
PS: I'd be very interested in some performance comparisons with Om and Vue.
I can't think of a good argument against it.
Then he uses a -webkit-animation to translate the positions of each ring.
@keyframes logo {
from {opacity:0;transform:scale(2) rotate(359deg);}
to {opacity:1;transform:scale(1) rotate(0deg);}
}
@-webkit-keyframes logo {
from {opacity:0;-webkit-transform:scale(2) rotate(359deg);}
to {opacity:1;-webkit-transform:scale(1) rotate(0deg);}
}the debate around the word just leaves a bad taste in my mouth. after reading arguments from both sides I would tend to agree: until the word is a word, it just sounds like marketing buzzword garbage.
Fair enough, but remember that a word becomes a word simply by usage, not by edict. The old Webster's rule was that, if a word appeared in ten recognized publications with a consistent meaning, it (the word and the definition) would be included in the next edition of the dictionary. I'm sure there's a similar rule in play today.
The fluid and pragmatic nature of words and their meanings can be gauged by noting that "literally" and "figuratively" now mean the same thing:
Link: http://www.merriam-webster.com/dictionary/literally
Quote:
1 : in a literal sense or manner : actually <took the remark literally> <was literally insane>
2 : in effect : virtually <will literally turn the world upside down to combat cruelty or injustice — Norman Cousins>
It would translate to overperforming. Compared to what? No one knows. It is oddly very used as a buzzword in marketing.
If so (I could be wrong), maybe it is not marketing but "pardon my french" juste like "idiot savant", "touché" and other french words that appears in the mouth of some that wants to look smart: it make us laugh very hard as a mix of posture and failure.
React is not "a templating language" that "uses a Virtual DOM", React is an implementation of _autonomous nestable components_, and that requires rerendering of HTML. Virtual DOM is just a way to achieve that rerendering better.
Obviously the author thinks so.
The fact that frameworks are appearing at a ridiculous rate is also the reason people still feel compelled to make their own: the existing ones sometimes feel thrown together and flawed in obvious ways, so people automatically think about ways they could be better and try those things out. The result is progress (edit: sometimes the result is a bag of crap, but that's beside the point).
No, we don't need more frameworks. And yet that still isn't a good reason to stop building them, if for no other reason than to explore for yourself what goes into building one (if that's your interest).
With JS the restrictions and limitations of the system are different. People are coming up with creative and innovative ways to work with them. There's no problem with that, it a process that's ongoing in all software, and forever will be.
Also, "You" should really avoid using "They", especially when it applies to a broad group of people that you're making assumptions and judgements about. Maybe "You" have no idea what HTML5 apps offer (like portability)? I happen to think that html5 is going to be a major player in apps development, which puts me in your "They" camp, then again, I know what native offers - so I'm one of the many contradictions to your statement.