📜 ⬆️ ⬇️

Developed by Mithril. Practice, experience and pitfalls



Synopsis


This article is based on the experience of developing a system application that constructs typical Landing-page on the parameters previously set in the control panel. The article will describe why Mithril was chosen for developing the application, its properties, advantages and what pitfalls can be found when using this wonderful tool.

Who might be interested in this article?


This article may be of interest to those who are studying the use of micro-frameworks for solving certain tasks that require convenient supported tools, with a light and practical architecture, and not loaded with a common shell. In addition, Mithril as a tool despite its small size has high performance - which is also not unimportant factor when choosing the right development tool. Interesting?

Why Mitrhil? Motivation to use


')

Briefly about Mithril himself - what is it and what is in it.


Mithril is an MVC micro-framework, the display model of which is based on Virtual DOM, which also adds rendering performance for large applications, or widgets that are compact but complex from the logic of drawing. Mithril-a has everything you need to call yourself a complete framework. There is a system for working with logic - controllers, tools for working with the binding of model data, and a full-fledged system for working with drawing. It also provides utilities for low-level control over the time and type of content redrawing (for example, for complex asynchronous operations), and compact add-ons:

All of these components and components allow you to develop mithril applications that will cover 90% of your needs while writing code.

Why chose Mithril?


During the elaboration of the architecture, the choice was between the client and server organization, given that the system itself was essentially minimally loaded with data, and all of them were typical, processing all requests, additional overlays in the form of template processing, their return, and the client’s waiting time were extremely unpleasant factors, since in our time the download speed and the “instantaneous” readability of the content is extremely important, and the extra load on the equipment is an extra cost.

Therefore, we soon discarded the server implementation option, and began to consider client-side options for tools that would allow us to solve with a small amount of blood (and unnecessary spent nerve cells) the range of tasks:
  1. Tool performance
  2. Convenient data organization.
  3. Control and speed of the drawing.
  4. Browser support: starting with IE9, as well as mobile browsers.
  5. Convenient and practical logic management, without excessive "applied" interactions
  6. Maximum compactness of the tool, without redundant functionality.
  7. Coming out of the last statement - the maximum "vanity" of the tool.
  8. Quick connection to the development of new developers not familiar with the tool.
  9. The possibility of adaptation in the future with the SEO.
  10. Component independent development - without the need for monolithic solutions.


Among the considered tools we considered a variety of libraries like - Angular , Angular Light , Backbone , Knockout , React . We also considered not only ready-made frameworks and complex tools, but also separate template systems, data libraries, etc.

Reasons for sifting out other tools

Why were all these options discarded during analysis? Here is a short overview of the list in which these tools were not relevant in the selection.
Angular and React are not suitable immediately because of their redundancy, because 99% of their functionality and organization will not be needed in the process.
Backbone - was eliminated due to excessively excessive logic, which remained an atavism of distant times, and the development on it would have put us in front of the choice of practically direct control of all content, and in general, the implicit structure of logic.
Knockout is an excellent library, but too large for a set of manipulations that are embedded in it, there are a lot of them and initially they are designed for a large amount of code for drawing in templates (with a link to data in logic and models). The management of the same logic as in Backbone is very specific, although it allows to work adequately with the data and the binding. In our application, this functionality was redundant - and it was decided to abandon this option as well.
Angular Light is a micro analogue of angular with a similar logic declared, including patterns, and “lazy” directives and components. From the original logic and behavior of directives from angular, not so much remains, a simplified but similar template system, a comparison system in the tree and the initialization of directives - by tag, class, attribute, and similarity of $ scope binding. A good tool - but it has a rather specific and not very flexible logic of component construction, and there were also initial difficulties in understanding its exact work. This option remained spare and working until the very end.

Mithril

When mithril hit the target of choosing a tool, it was already quite a mature and accomplished project of a toolkit for writing applications without frills, but with full-fledged functionality. This tool did not have those atavisms or excessive template logic like Backbone or Knockout - in fact mithril was a small shell over DOM elements, most of the events of which were directly tied to DOM methods, with a little added sugar in the form of Virtual DOM and attached to the object controller logic In this case, data binding, and most of the excesses were excluded from the logic - which opened the maximum flexibility for implementation. He gathered in himself all the minimalism and practicality that is necessary when developing capacious and expandable applications. Unlike Angular Light, it had a more transparent component logic, more practical and unified - which made it easy to maintain the code, and not think about sudden problems with the intricacies of the architecture.

Induce beauty - sugar, convenience, utility


By default, the development of components on mithril is really a process in which absolute nothing rules, you can use many different tools and libraries to your liking for greater ease of development, but I believe that there is a basis that will be useful to everyone who starts developing their applications on mithril.

General Tips, Patterns, Classes and OOP

Templates
By default, in Mithril, as in React, the writing of template nodes is rather inconvenient in an organized way, even though the DOM element query construction simplification system is:

//     "class" . m('div', { "class": "container-class" }, [ // ..    ,         .  . m('h1[withattr="attr"]', { onclick: function(event) { /*    */ } }, 'Header') ]); 

Especially this feature is felt if you are accustomed to using plain HTML, and do not want to bother with the complexity of the mithril display architecture. For this, there is a special transformer - MSX , and shells for it - such as, for example, the most convenient babel-plugin-mjsx for my Babel compiler.
Which allows you to use similar designs that are so familiar to us from React JSX:

  <div class="container-class"> <h1 withattr="attr" onclick={ (event) => { /.../ } }>Header</h1> </div> 

In my opinion, this option (MSX) will be very convenient to use this kit:
gulp + browserify + babelify + msx .
Here is an example of use.

 //     Babel      . var Compiler = babelify.configure({ //     babel core optional: [ 'es7.exponentiationOperator', 'es6.spec.blockScoping', 'es7.exportExtensions', 'es7.classProperties', 'es7.comprehensions', 'es7.decorators' ], //     plugins: [{ transformer: MSX, //  MSX position: "before" //     }] }); gulp.task('babel-msx', function() { browserify([ /*   */ ]) .transform(Compiler).bundle() //    Browserify .pipe(source('bundle.js')) .pipe(gulp.dest('build/')); }); 


Classes and OOP
In 2015, ES6 began to acquire special popularity ( or its expanded draft “sugar” edition of ES2015 “ES7” ) and compilers like Babel or Typescript that transform it into ES5: many people wanted to fully start using its maximum capabilities, including support for classes, decorators , and much more. Already existing frameworks (for example, Angular 2.0 ) began to adapt to new realities, as well as to appear - such as Aurelia , and therefore the use of all capabilities, and the flexibility of tools to these capabilities - for many may be an important factor in the development.

By default, Mithril is organized inside a regular object, which can be a separate component in the architecture, and the organization’s special capabilities for use as classes are not implemented, for reasons of the same minimalism, but this does not mean that you cannot expand or adapt to Object Development in this tool.

In the simplest version, you simply need to use the component object as an instance of a class — like this:
 /*   */ class Component { constructor(opts) { /*     ... */ this.opts = opts; /*      */ this.controller = this.controller.bind(this); this.view = this.view.bind(this); } /*   */ controller(props) { return { paramOne: this.opts.paramOne }; } /*   */ view(ctrl, props, children) { return ( <button onclick={this.method} attr={ctrl.paramOne} /> ); } }; /*   -      */ m.mount(document.body, new Component({ paramOne: 'Hello!' })); 


This is the easiest way to use classes in Mithril - but nevertheless it’s still not an ideal option, which also takes into account some features, for example, you shouldn’t store absolutely all data in an instance and suppose storing them in view - so you don’t illusoryly risk say goodbye to the data during the subsequent redrawing - so the logic and the data are best kept separately. At the same time, storing data and manipulating them in the controller is also not the best way out - then you have to create a whole dependency tree if you have to transfer data to the component hierarchy, which does not add simplicity and maintainability to the “vanilla” code.

You can, for example, use when building the Flux Store application or any other storage that is most convenient for you to use - and adapt it inside the component, then you will have a clear hierarchy of data storage, processing, and a clear boundary of abstract event operations within the instance — such as an index of an activated tab, etc. Events actions you can bind to the render, draw, and even create an improvised semblance of a living cycle as in React with its componentWillMount, componentDidMount, etc.

Architectural features, pitfalls, personal notes


Drawing

Mithril is based on Virtual DOM and this is one of its distinguishing features, which gives it its speed and performance, but considering that it is a minimalistic framework, there are features in its rendering system that may initially surprise developers a little, for example, those who already had some experience in React . For example, in Mithril, you cannot control the repainting of a single node or component separately from all other components - as you could do for example in React. And it imposes some difficulties with understanding - so it’s worth understanding how the redrawing works in Mithril.
In user access, there are 2 types of redrawing:

m.startComputation / m.endComputation - methods that allow you to work with state organization when redrawing, literally - they denote segments of the first VDOM tree snapshot, and the second snapshot, then both snapshots are compared, and after the changes found they form a patch - which changes the data. This is useful, for example, when loading asynchronous data, in which case you take the first snapshot before the start of operations, and take the last snapshot after you get the result. Of the features worth noting - that the methods globally compare the entire tree as a whole, even if you called them in any particular component, so you should take care when developing that redrawing does not affect other components in the tree. Here is a simple usage example:
 function asyncGetAndRedraw() { /*      */ m.startComputation(); /*   */ SomeAsyncOperation({ ...args }).then(function promised(data) { /*   (   ) */ setTarget = data; /*     ,    ,   */ m.endComputation(); }); }; 


m.redraw is a method for hard drawing, a comparison is not made when calling this method, the method completely redraws the entire tree of components, follows this method with extreme caution, because when redrawing it does not take into account the already existing states of the components.

Using plain HTML in components

A rather dangerous and not recommended operation, but there are times when you need to insert a string of template pure HTML, and the m.trust method will help with this, here's how it can be used.

 m.render("body", [ m("div", m.trust("<p>Clean Html</p>")) ]); 


Finally


In this small article, what was interesting is the Mithril micro-framework when developing web applications, what advantages it has, a comparative analysis with other tools (by personal assessment and needs), as well as some sugar and notes on the use of this framework by the philistines . From the above, I think it is worth emphasizing that Mithril is primarily intended for writing compact, capacious web applications (for example, widgets) that need maximum efficiency and conciseness in development - coupled with performance. Although if you think carefully about the architecture, add your implementations, methods and a couple of superclasses and decorators as wrappers - this tool will not let you down on large projects and web applications. The article presented my opinion and observations on the use of mithril - if you also have experience using this system or the subtleties that you discovered for yourself - it would be very interesting to learn about them. I expect that the article was interesting and useful to read.

Additionally


Official site.
Framework Page on github
Useful articles about using Mithril

Source: https://habr.com/ru/post/272449/


All Articles