Riot.js入門と、compile・precompileのはなし


## component志向のフレームワーク！

あちこちで **「いまはReact.jsよりRiot.jsだぜ！！」** という声が聞かれるようになったので、入門したくなりました。
（いまの勢いで言えばReact.jsをちゃんとやっておくべきなんだろうけど、どうしてもJSXの記法が受け入れられない…）

さてさてRiot.jsとは。以下あたりを見ると分かりやすいです。

- [Riot.js — A React-like user interface micro-library · Riot.js](http://riotjs.com/ja/)
- [フロント界隈で一番イケてるのは AngularJS でも React でもなく Riot.js だという話 | phiary](http://phiary.me/frontend-riot-js-no1/)

担っている役割としてはReact.jsに近いですが、ReactがMVCで言うところのViewだと断言しているのに対して、Riot.jsはMVC（あるいはFluxとか）というよりは **Webコンポーネントのフレームワーク** だという文脈で説明されることのほうが多いようです。
(そういう意味では[Polymer](https://www.polymer-project.org/1.0/)との比較の方が適切かも)

Webコンポーネントとはざっくり言えば、
普段HTMLとして使っている`h1`とか`li`とかの拡張版として、`sidebar`とか`global-menu`とか`todo-list`とか、そのWebアプリでしか使わないものも定義してしまって、その組み合わせでWebを構築しようという考え方です。
この各コンポーネントは見た目だけの意味ではなく、その部分が持っている振る舞いも内包しているので、これをほしいところにホイッと置けば万事うまく動く！というのを理想としてます。

実際触ってみた感じ、Viewだけを担うというより、全部をRiot.jsに任せたほうがきれいに組み立てられそうなイメージありました。

## 使ってみよう！

なんとなく世に出回ってるサンプルが、「ほら！Riotで書くとすごいよ！短いよ！！」みたいな物が多くて組み込み方が分かりづらかったので、もうちょっとすぐ動くサンプルをば。（コピペしてブラウザで開けば動くはずです）

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Riot Demo</title>
  </head>
  <body>
    <!-- ここに、TODOリストのコンポーネントができてほしい -->
    <todo></todo>

    <!-- 「todoタグ」の定義 (外部ファイルに書いて、srcで読み込んでもよい) -->
    <script type="riot/tag">
      <todo>
        <ul>
          <li each="{ list }">{ name }</li>
        </ul>

        <style>
         todo li {
           margin: 0.5em;
           padding: 0.5em;
           background-color: #eee;
         }
        </style>

        this.list = opts.list;
      </todo>
    </script>

    <!-- riot.js本体 -->
    <script src="https://cdn.jsdelivr.net/g/riot@2.0(riot.min.js+compiler.min.js)"></script>

    <!-- mount!! -->
    <!-- (<todo>を書いていた部分に、定義したtodoタグの振る舞いを実際に与える その際データを渡したりする) -->
    <script>
      riot.mount('todo', {
        list: [{
            name: "やばい"
        },{
            name: "まじで"
        },{
            name: "はんぱない"
        }]
      });
    </script>
  </body>
</html>

```

こちらの `<script type="riot/tag">` というあたりが、今回使っている`todo`というコンポーネントの定義部分になります。
HTMLの構造と、スタイルと、データをどのように取り回すかという振る舞いの部分、すべてを１箇所に書いているのが分かります。
(もっと細かい使い方は、[公式](http://riotjs.com/ja/guide/)読むのが一番わかります。)


## compileとprecompile

上記のサンプルでは、HTMLの構造・スタイル・振る舞いがまとまったコンポーネントの記述を、riot.jsがブラウザ上でいい感じに解釈して、即実行していたのですが、この「解釈 = コンパイル」の部分を事前にやった上で読み込ませることもできます。（プリコンパイル）

定義の部分はだいたいの場合、アクセス毎に動的変化したりしないので、事前にやってしまったほうがパフォーマンスがよいのと、
プリコンパイルを使う場合は、コンポーネントの記述に[様々な別の言語を用いる](http://riotjs.com/ja/guide/compiler/#section-9)こともできるようになっているので、言語にこだわりがあるあなたも安心です。
（自分は`<``>`を書くのがもう嫌になってきたのでpug使います）

なお、コンポーネントをブラウザでコンパイルする場合と、プリコンパイル済みのコンポーネントを使う場合で、使うべきriot.jsのセットや読み込み順が変わってくるので、ちょっと注意です。

### ブラウザでコンパイルする場合

```html
<!-- mount先 -->
<todo></todo>

<!-- tagの読み込み(コンパイル前のものなので、typeは"riot/tag") -->
<script src="todo.tag" type="riot/tag"></script>

<!-- riot.js本体（コンパイラ付き） -->
<script src="https://cdn.jsdelivr.net/g/riot@2.0(riot.min.js+compiler.min.js)"></script>

<!-- mount実行など -->
<script>
  riot.mount('todo');
</script>

```

### プリコンパイルする場合

```html
<!-- mount先 -->
<todo></todo>

<!-- riot.js本体（コンパイラなし） -->
<script src="//cdn.jsdelivr.net/riot/2.5/riot.min.js"></script>

<!-- tagの読み込み(コンパイル済のものなので、typeはjavascriptである) -->
<script src="js/tag/todo.js"></script>

<!-- mount実行など -->
<script>
  riot.mount('todo');
</script>
```

コンパイル前のタグは、riot.jsが読み込まれる時点で文書に存在する必要があるので、riot.jsよりも **前に** 、
コンパイル済みのタグは、riot.jsに含まれるメソッドに依存したjavascriptになっているので、riot.jsよりも **後に** 読み込まなきゃいけないというのがミソです。


## 考慮しなくちゃいけないこと

さて、いい印象を多めに書いた記事でしたが、やはり「どんな状況でも使いたい！」とまではいかないかと。
以下のような懸念点がある気がするので、ベターな手段を使うようにしましょう。

- javascriptでのレンダリングを考慮に入れない場合はからっぽのHTMLになるので、例によってSEOが激弱になる。
  - サーバーサイドレンダリングもできるようなので、それができる場合はそうしましょう。

- 振る舞いのjsが膨らんできた時に、どこまでをコンポーネントに書くか、というあたりは一考が必要。肥大化したcomponentばかりになってきたら悲劇しかなさそう。

- コンポーネントはひとつのファイルに色んな物を記述する宿命にあるので、ソースコードの検索性が落ちそう。

## 参考記事

- [RiotをReact・Polymerと比較する · Riot.js](http://riotjs.com/ja/compare/)
- [Riot.js 2.0 を触ってみた — まだReactで消耗しているの? - Qiita](http://qiita.com/cognitom/items/fb1295f3f93911e9e92d)
- [Riot.jsのHTML部分をJadeで書いてgulpするメモ - Qiita](http://qiita.com/narikei/items/10e7c9613e362b52314e)
- [Riot 2.0を試してみる（Compiler編 - Qiita](http://qiita.com/kazusa-qooq/items/e1f3ca2990b3aed0e300)