advanced mithril.js & learnings 

Agenda

  • quick intro

  • do's

  • don'ts

  • components

  • isomorphic apps
  • testing
  • migrating your app to mithril.js
  • How to handle DOM-stuff

Me

  • JS-Dev since 2011

  • Founder of tutory.de

  • JS-Only Freelancer since 2014

Currently working on three mithril projects

tutory.de

  • Online OER-Editor
  • Build from scratch with mithril

??

  • Browser based newspaper planing tool
  • Build in Java ("Native" App)
  • Rebuild with backbone/ampersand
  • Now in the process of conversion to mithril

??

  • Universal shop plugin
  • Prototype build with jquery
  • Now reimplementation with mithril

Quick Intro

What is mithril.js

Functional (M)VC

uses VDOM

like react

small API

small diving depth

fast

small filesize

do's

try it

it seems uglier than it actually is

combine it with tools you like

gulp, moment, backbone(-models), browserify, emberjs

embrace functional programming

trust your intuition

it mostly works as you would expect

use mithril components

they are awesome

don'ts

no heavy computing in views

use controllers

no super-heavy computing in controllers

use models instead

see here

beware of premature optimisation

components

standard mithril app

m.mount(yourBasicDOMel, {
  controller: function() {
    return {
      name: 'Superman'
    };
  },
  view: function(scope) {
    return m('.name', scope.name);
  }
});

mithril component

nameComponent = {
  controller: function() {
    return {
      name: 'Superman'
    };
  },
  view: function(scope) {
    return m('.name', scope.name);
  }
};

usage

m.mount(yourBasicDOMel, {
  controller: function() {
    // ...
  },
  view: function(scope) {
    return m('.container', nameComponent);
  }
});

mithril component

nameComponent = {
  controller: function() {
    return {
      name: 'Batman'
    };
  },
  view: function(scope) {
    return m('.name', scope.name);
  }
};

usage

m.mount(yourBasicDOMel, {
  controller: function() {
    return {
      foo: 'bar'
    };
  },
  view: function(scope) {
    return m('.baz', 
      m.component(barComponent, 'Superman')
    );
  }
});

mithril component

nameComponent = {
  controller: function(initialName) {
    return {
      name: initialName || 'Batman'
    };
  },
  view: function(scope) {
    return m('.name', scope.name);
  }
};

Parameter

Isomorphic apps

possible

tutory.de has integration in express webserver

with the help of mithril-node-render

Do you really need it for a SPA?

It's only relevant for search engines

so only pre-render indexed pages

Prerender does not improve render performace

since mithril rerenders everything on startup

testing

Is powerfull!

Is fast!

Is easy!

Basic Example

var out = mithrilQuery(nameComponent, 'Catwoman');

out.should.have('.name');
out.should.not.have('.address');
out.should.have(1, '.name');
out.should.contain('Catwomen');

mithril component

test for component

nameComponent = {
  controller: function(initialName) {
    return {
      name: initialName || 'Batman'
    };
  },
  view: function(scope) {
    return m('.name', scope.name);
  }
};

Advanced Example

mithril component

test for component

var out = mithrilQuery(nameComponent, 'Catwoman');

out.should.contain('Catwomen');
out.click('.clear');
out.should.not.contain('Catwomen');
nameComponent = {
  controller: function(initialName) {
    var scope = {
      name: initialName || 'Batman'
      clearName: function() {
        scope.name = '';
      }
    };
    return scope;
  },
  view: function(scope) {
    return m('.name', scope.name);
    return m('.clear', {
      onclick: scope.clearName
    }, 'clear');
  }
};

Migrating your app to mithril

It's possible

Start from the leafs

Rebuild small parts of your app with mithril and make multiple mounts

Handling redraws can be tricky

since mithril has only one redraws cycle for all mounts

Handle DOM-Stuff

It's possible

It's easier than you might think

Example

function drawCanvas(element, isInitialized) {
   //don't redraw if we did once already
   if (isInitialized) return;

   var ctx = element.getContext("2d");
   /* draws stuff */
}

var app = {
  controller: function() {
    // ...
  },
  view: {
    return m("canvas", {
      config: drawCanvas
    })
  }
]

m.mount(document.body, app);

Conclusion

I still love it

maybe even more now

It's my golden hammer

All other stuff seems so odd compared to mithril

Questions

Thanks

mithril

By Stephan Hoyer

mithril

  • 1,639