http://moonjs.ga/

Moon

Moonは軽量で高速なUIライブラリです。Mediumの「Introducing Moon」では開発された経緯と紹介、他のフレームワークとの比較がされています。

なぜMoonを採用するのか

公式資料ではMoonは軽量で高速なライブラリであると述べています。

  • Preact - 3kb
  • Moon - 7kb
  • Mithril - 8kb
  • Vue - 25.86kb
  • React + React DOM - 43kb
  • Angular - 111kb

パフォーマンスに関して、1秒間のレンダリング回数のベンチマークが取られています。Incremental-DOMとInfelnoも気になります。

  • Moon - 102/min
  • Mithril - 95/min
  • Angular - 62/min
  • Vue - 50/min
  • React - 49/min

Moonはpolyfillを必要とせずにIE9+をサポートしています。AngularやVueのような最近のライブラリの殆どはBabelやTypeScriptを必要としIE9のサポートをやめています。

Vueのように、CDNが存在しそのままブラウザで動作させることができます。

UIの為にjQuery3のゴミを省いたスリムビルドでも67.3KBであることを考えると、7KBのMoonを採用する価値は十分にあります。

MoonはUIコンポーネントを可読性の高いコードで高速に構築することを重視しています、それはクライアントサイドルーティングの大規模なシングルページWebアプリケーションを構築するには、おそらく向いていません。

アプリケーション設計

VueとReactに関してはVuexやMobxのような他のライブラリがあるようにMoonにもMonxというライブラリがあります。

Monxは598 bytesのシンプルかつ軽量なデータフロー設計を助けるライブラリです。

コンポーネント間の状態の依存関係を取り出すことで、コンポーネントを綺麗にテストしやすいものにしてくれます。

初期のMobx-State-Treeから型定義を無くしたようなAPIで、読みやすいシンプルな文法で出来ています。

CLI

MoonにはCLIがあります。

今のところ、あまり多くの機能は無いみたいです。

$ npm install moon-cli -g
$ moon init moon-example
======= MOON =======
[?] Author uufish
[?] Description A Moon App
[?] Moon Version 0.11.0
✓ generating template
success generated ‘moon-example’ ✨
To Start, Run:
cd moon-example
npm install
npm run dev
$ cd moon-example

必要なモジュールをインストールして起動します。

開発環境の生成が終わったらnpm-scriptのdevを実行します。

$ yarn
$ yarn dev

開発環境が起動し、webサーバーが立ち上がります。

js/components/header.moonのtemplateを書き換えることでホットコードを体験することができます。かなり高速で反応します。

開発環境

Moonはfuse-boxやwebpackを必要としていません。buildというディレクトリが存在し、それをnodeで実行することでサーバーが起動します。

browserify-hmrやwatchifyといったモジュールが採用されています。コードも少なく読みやすいので、既存のプロジェクトにも簡単に導入することができます。

$ watchify -vd -e js/scripts.js -o dist/js/build.min.js -t moonify -p browserify-hmr

Moonは.moonという拡張子のファイルをコンパイルします。テンプレートはVueにとても良く似ており、理解し易いです。

ただテンプレートの解析ができる環境を用意する必要があります。Atomではプラグインがあります。

コンポーネント

.moonでひとつのコンポーネントを設計できます。

<template>
<h1>{{content}}</h1>
</template>

<style scoped>
h1 {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-weight: 200;
font-size: 100px;
color: #414141;
}
</style>

<script>
exports = {
props: ["content"]
}
</script>

ここで、contentはpropsであり、Html側から属性として渡すことができます。

<div id="app" m-mask>
<Header content="Moon"></Header>
</div>

.moonのtemplateを見ればこれが、h1のchildrenであることがわかります。

このようにコンポーネントを使用したい場合は、コンポーネントを関数として実行します。

最後にMoon関数を実行することでレンダリングされます。

const Moon = require('moonjs')
const header = require('./components/header.moon')
header(Moon)

new Moon({el: '#app'})

ライブラリ

UIライブラリを作りたいなら1つの.moonファイルを書くだけです。もし依存性注入のようなことがしたいのならmonxのstoreを書くのがいいかもしれません。

moon-barsというライブラリが参考になります。

また、設計に関してはサンプルがいくつかあります。みんなの愛するTodoMVCもちゃんとあります。

もし既存のサービスに、ポップアップやデイトピッカー、スナックバーのようなちょっとしたUIコンポーネントを実装したいなら、Moonを使用するといいかもしれません。