Mithril 1.1.0

イントロダクション


Mithrilとは?

Mithrilはシングルページアプリケーションを構築するためのモダンなクライアントサイドのJavaScriptフレームワークです。サイズは小さく(< 8kb gzip)高速で、ラウティングやXHRといったユーティリティもパッケージ内に内蔵しています。

ダウンロードサイズの比較
Mithril (8kb)
Vue + Vue-Router + Vuex + fetch (40kb)
React + React-Router + Redux + fetch (64kb)
Angular (135kb)
パフォーマンス
Mithril (6.4ms)
Vue (9.8ms)
React (12.1ms)
Angular (11.5ms)

MithrilはVimeoやNikeといった企業や、Lichessのようなオープンソースプラットフォームで利用されています。

もし、すでにJavaScriptのフレームワークでの開発経験があり、他のフレームワークとなにが違うのかを知りたければ、フレームワークの比較のページを見てください。

MithrilはPolyfillなしでIE9以降のすべてのブラウザに対応しています。


はじめよう

CDNを使ってMithrilを読み込んで、これから説明するチュートリアルをなぞるのが、Mithrilを試すもっとも簡単な方法です。このチュートリアルはラウティングやXHRも含めて、主要なAPIを紹介しますが、10分程度しかかかりません。

それでは次のようなHTMLファイルを作ってみましょう:

<body>
    <script src="//unpkg.com/mithril/mithril.js"></script>
    <script>
    var root = document.body

    // ここにコードを追加していきます
    </script>
</body>

Hello world

まずはなるべく小さなステップから始めましょう。スクリーンにテキストを表示してみます。次のコードをコピーして、最初に作ったファイルにコピーしてみましょう(コピーと言いましたが、タイピングした方が学習効果は高いでしょう)。

var root = document.body

m.render(root, "Hello world")

別のテキストに変えてみましょう。次の行を前のサンプルに追加してください。

m.render(root, "最初のMithrilアプリケーション")

このコードを見ればおわかりの通りに、同じコードをつかってHTMLの作成と更新を行うことができます。Mithrilは自動的にテキストを更新するためのもっとも効率的な方法を判断して実行します。盲目的にすべてを再作成することはありません。


DOMエレメント

次に、テキストを<h1>タグでくくってみましょう。

m.render(root, m("h1", "最初のMithrilアプリケーション"))

m()関数を使うと、あらゆるHTML構造が表現できます。<h1>タグにクラスを追加するには次のようにします:

m("h1", {class: "title"}, "最初のMithrilアプリケーション")

複数のエレメントを追加してみましょう:

[
    m("h1", {class: "title"}, "最初のMithrilアプリケーション"),
    m("button", "ボタン"),
]

さらにタグで囲って階層化してみます:

m("main", [
    m("h1", {class: "title"}, "最初のMithrilアプリケーション"),
    m("button", "ボタン"),
])

Note: もし<html>という文法を使いたい時は、Babelプラグインを使うと利用できます。

// BabelのJSXをプラグインを使ったHTML文法
<main>
    <h1 class="title">最初のMithrilアプリケーション</h1>
    <button>ボタン</button>
</main>

コンポーネント

Mithrilのコンポーネントはview関数を持つ単なるオブジェクトです。上記のコードをコンポーネント化してみましょう。

var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "最初のMithrilアプリケーション"),
            m("button", "ボタン"),
        ])
    }
}

コンポーネントをアクティベート化するにはm.mount()関数を使います。

m.mount(root, Hello)

期待されるように、次のマークアップが生成されます:

<main>
    <h1 class="title">最初のMithrilアプリケーション</h1>
    <button>ボタン</button>
</main>

m.mount()関数はm.render()関数と似ていますが、後者は一度しかHTMLをレンダリング(DOMの生成)を行いません。前者はMithrilの自動再描画システムを起動します。この意味を理解するために、イベントを追加してみましょう:

var count = 0 // 変数を追加
var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "最初のMithrilアプリケーション"),
            // この行を変更
            m("button", {onclick: function() {count++}}, count + " クリック"),
        ])
    }
}

m.mount(root, Hello)

ボタンに対してonclickイベントを追加しました。このイベントは、コードの先頭で宣言されているcount変数をインクリメントします。そして、この変数の値をボタンのラベルとして表示するようにしました。

ボタンをクリックすると、ボタンのラベルが更新されるようになります。m.mount()を使うと、m.render()をマニュアルで呼び出さなくてもcount変数の変更をMithrilがHTMLに反映します。

パフォーマンスについて気になる方もいるでしょう。Mithrilは、本当に必要なDOMの部分にしか触れないため、レンダリングの更新時を非常に高速に行います。上記のサンプルでは、ボタンをクリックしたときには、MithrilはボタンのテキストのDOM部分だけを更新します。


ラウティング

ラウティングは、アプリケーション内のいくつかのスクリーン間で移動することです。

クリックカウンターの前に、スプラッシュページを追加してみましょう。まず次のコンポーネントを作成します:

var Splash = {
    view: function() {
        return m("a", {href: "#!/hello"}, "ようこそ!")
    }
}

このコンポーネントは、#!/helloへのリンクをレンダリングするだけのシンプルなものです。#!部分はハッシュバング(hashbang)と言われています。これはシングルページアプリケーションで一般的にみられる慣習です。このハッシュバングの後の部分(/helloパート)がラウトのパスです。

アプリケーションが複数のスクリーンを扱う時はm.mount()の代わりにm.route()を使います。

m.route(root, "/splash", {
    "/splash": Splash,
    "/hello": Hello,
})

m.route関数はm.mountと同じ自動再描画機能を持っています。これに加えて、URLの変更に対応することができます。URLに#!の文字を見つけたら、Mithrilに何をするか教えます。

rootのすぐ右にある"/splash"はデフォルトのラウトです。ハッシュバングのあとのURLが、定義されているラウト(このサンプルでは/splash/hello)、MithrilはこのURLにリダイレクトします。もしブラウザを開いて、そのページのURLがhttp://localhostだったら、http://localhost/#!/splashにリダイレクトします。

スプラッシュページのなかのリンクをクリックすると、以前作ったクリックカウンターに移動します。新しいページに移動するとURLはhttp://localhost/#!/helloになります。ブラウザの「戻る」「進む」ボタンを使って、スプラッシュページにいったりきたりナビゲーションできます。


XHR

基本的にXHRはサーバーと話をするための方法です。

クリックカウンターを修正して、サーバーにデータを保存できるようにしましょう。サーバーには、チュートリアルのようなおもちゃアプリケーションのために作られた、モックのREST APIを提供するREMを使います。

まず、m.requestを呼び出す関数を作ってみましょう。urlはリソースを表すエンドポイントを指定します。methodは話をするアクションの種類を指定します(upsertsには通常PUTメソッドを使います)。dataはエンドポイントに送付するペイロードです。withCredentialsはクッキーを有効化する(REM APIを動作させるのに必要)ために指定します。

var count = 0
var increment = function() {
    m.request({
        method: "PUT",
        url: "//rem-rest-api.herokuapp.com/api/tutorial/1",
        data: {count: count + 1},
        withCredentials: true,
    })
    .then(function(data) {
        count = parseInt(data.count)
    })
}

{count: 1}オブジェクトを付けて、/api/tutorial/1のエンドポイントで公開されているインクリメントをするupserts関数を呼び出しています。このエンドポイントは、送信したときと同じcount値のオブジェクトを返します。count変数はリクエストの完了後にのみアップデートされます。そして、この値はサーバーからのレスポンス値で更新されます。

それではコンポーネントのイベントハンドラーを修正しましょう。今まではcount変数を直接扱っていましたが、increment関数を代わりに呼びだします。

var Hello = {
    view: function() {
        return m("main", [
            m("h1", {class: "title"}, "最初のMithrilアプリケーション"),
            m("button", {onclick: increment}, count + " クリック"),
        ])
    }
}

ボタンをクリックするとカウントが更新されます。


本チュートリアルではHTMLの作成と更新方法、コンポーネントの作成方法、シングルページアプリケーションのためのラウト。サーバーとのインタラクションを説明してきました。

これらの内容は、本物のアプリケーションのフロントエンドを書き始めるには十分でしょう。Mithril APIの基本についてはここまでの説明で触れたところで十分に快適に使えます。シンプルなアプリケーションを作成するチュートリアルは、より実践的なアプリケーションの構築方法について説明しています。


License: MIT. © Leo Horie.