2016-12-07

AMESTAGE を支える Riot.js とその構成について紹介

この記事は Riot.js Advent Calendar 2016 の 7 日目の記事です!!


Riot.js で芸能人とあそべる生放送サービス AMESTAGE というのを作っていて、動画サービスだったり、芸能人と一緒に遊べるクイズやコメント・ランキングといった各種機能盛りだくさんなせいか、そこそこ規模が大きくなってきました!


是非遊んでみてください!!


そんな AMESTAGE での Riot.js との付き合い方について、どういう構成でやっているかをサーバー構成からビルド方法、Atomic Design というデザイン手法の導入、Flux な構成までザックリ紹介してみようかなと思います!


基本構成

Node.js で Web サーバーを建てて、API サーバーやログイン基盤とのやり取りをまとめています。API サーバーを直接ブラウザからは叩きに行かず、 Web サーバーに実装した API を必ず介してデータを取得しています。

最近あった「リクルートテクノロジーズのフロントエンド開発 2016」という記事のBackend for Frontend なサーバー構成に似た状態です。

サーバーサイドレンダリングはほぼやってませんが、ロボットからのアクセスに対して riot.js の機能を使って SEO 向けページを用意していた事もありました。
テンプレートエンジンは ECT を利用しており、Riot.js のレンダリングを待ちたくないヘッダー等の簡単なマークアップはそちらで済ませてしまっていたりします。

コーディング

Babel を使っています。eslint でコーディングルールを管理し、babelrc, eslintrc の設定に riot のプラグインなどを追加しています。あとは editorconfig も追加しています。(エディタはvimが多め)

ビルド周り

Riot.js は gulp を使ってコンパイルしたものをブラウザから読み込ませています。ファイルを分けている各 js は Browserify を利用して1つにまとめています。

Browserify を使うときは注意が必要で、今の構成でビルドするには Browserify + Babelify + Riotify だけで動きはするのですが、これだとファイルが増えていったときに watch しながら実装していると、1ビルド毎に何十秒もかかってしまい、開発効率が悪くなってしまいます。

なので差分ビルドができるように、 watchify というものを追加します。差分ビルドだと、import (require) しているファイルたちを毎回全部くっつけてた処理が、変更のあったファイルのみ再ビルドされるだけになるので2〜3秒とかほんの僅かな時間でビルド可能になります。これやらないと、本当に死ぬので是非お試しください。

ポイントは browserify で作るエントリーポイントを少なく(出来れば1つに抑える)構成すると開発もスムーズに行くと思います。今からやるのであれば、 WebPack を試してみるのも良いのではないでしょうか。

その他 gulp ではサーバー起動と watch からの js / css ビルド or minify 処理がメインです。sourcemap 作ったりとかとか。


Flux

Riot.js の Observable を使ったシンプルな flux を実現しています。Redux とかは使ってなくて、お手製です。でも Redux 等も良いと思います。
Riot.js を使ったコンポーネント志向な造りになるときは、Flux なデータの受け渡しはとても相性が良いです。ぜひ導入しましょう。

文章だけでは難しいですが、イベント名と紐付いた store を1つのオブジェクトに登録して、context みたいな形で riot.mixin してどのタグからでも同じデータを見れるようにして使っています。


Flux の実装については簡単に説明すると View から実行された action で API の結果だったり、渡したいデータを決まったイベント名で trigger して、dispatch にデータを渡します。

dispatcher に登録した store にそのイベント名で受けたデータを反映させ、 store にはデータが保存されるので、view では store のデータを引っ張ってきたり監視して変更を反映させたりするだけとなっています…

…がやっぱり分かりづらいので細かい実装などについては、直接ご相談いただければお話させていただきますのでお気軽にご連絡ください^^


Atomic Design と Style Guide

色んな勉強会などでお話させてもらってる Atomic Design ですが、こちらは components というディレクトリ以下に Atoms, Molecules, Organisms という単位でそれぞれを管理しています。以前会社ブログに書かせてもらったこの記事でも紹介していますが、具体的にはこんな感じ。

components/
├── Atoms
│   ├── follow-button
│   │   ├── _follow-button.scss
│   │   ├── follow-button.tag
│   │   └── example.tag
│   └── atom-component-name
│       ├── _atom-component-name.scss
│       ├── atom-component-name.tag
│       └── example.tag
├── Molecules (Atomsと同じ構成)
├── Organisms (Atomsと同じ構成)
├── styleguide
│   ├── style-guide-item.tag
│   ├── styleguide.html
│   └── style-guide.js
...

それぞれはコンポーネント本体、そのscss、example.tagには Style Guide での使われ方や表示に必要なテストデータが入ってます。
example.tag ファイルの実装は、Style Guideでの見え方の他に、サイズやその他種類など、同コンポーネントでの表示パターンをなるべく網羅するように記載しています。

今後はこのexample.tag のデータに紐付いてテストもまとめて書けたらなぁと妄想しています・・・(´・ω・`)

開発時は gulp style と実行すると style guide 用のサーバーが立ち上がり、コンポーネントの見た目を作るときはそれを見ながら実装できます。

Atomic Design と Style Guide については今までにも勉強会などで話させてもらった資料などを公開していますのでそちらも合わせて御覧ください!

勉強会に登壇した話とデザインエンジニアリングについて

Riot.js 勉強会を主催しました


スタイルの当て方について

riot.js の tag 内でも sass は使えるのですが、コンポーネント実装をやっていく上で複雑な動作があるものに関してはマークアップが長くなったりと色々不便があったり、スクリプトまで書くと全体的に長くなってしまうなという印象がありました。
なので sass ファイルを別にしています。あえて .tag 内に書いていません。

例えば、 atom-icon.tag みたいなコンポーネントがあったとしたら、_atom-icon.scss を同ディレクトリに置いて、そのタグ名で以下のようにスタイルを記述していきます。

atom-icon {
  height: 100px;
  width: 200px;
}

こうすることで直感的にこのタグ内でのスタイルだけに集中して書くことができるので、riot.js v3ではデフォルトになった scoped な書き方が出来ます。
class 名なども、コンポーネント間で完結するのでかぶること無く(もし被っても子タグclass 名の方が強いので問題になったことがない)BEMのような管理をしなくて済むのでとても見通しが良いです。

各 components の sass は gulp-sass と gulp-sass-glob を使って1つのファイルにまとめてから minify などしてます。共通して使ってる色や数値は変数にして共通して使えるように利用しています。


その他ライブラリについて

jQuery 系を使ってません。DOM 操作がそもそもそんなにやること無いのと、class の付け替えや DOM の切り替えなんかは riot.js の機能だけで十分出来てしまうからです。
無駄なファイル読み込みが減るので、思い切って使うこと自体をやめてみました。

あとは bugsnag でバグ確認したりとか、色々楽しく動くサービスだったりするので必要なアニメーション系ライブラリを導入予定です。anime.js とか。現時点ではコーナーやギフトと言われるアニメーションは css をコツコツ手付けでやってたりします。


テスト準備中。。

言い訳になるので理由は言いませんがテストが今無くて準備中です。。使おうと思ってるのは Riot.js でも使われてるので karma-riot を考えてます。

コンポーネント単位でのスタイル確認は Style Guide でやってます。まだ構想なのですが、今後はこの Style Guide 確認と一緒に karma のテストが書けたらなと思っています。
Style Guide 自体が今 AMESTAGE 用に作られているので、しっかり外部 module 化して、オープンソースにしたりとかも出来たら良いな…とかとか(妄想)React にある Storybook 的なやつがとても良さそうなので、それに近いものを…!


まとめ

ざざっと全体像を書くことになってしまったので、詳細について端折りすぎた感じが申し訳ないのでどこかで書くか発表するか、質問・リクエストくださいw

これらの構成自体は全然正解ではないし、このあともどんどん改良していこうと思ってるものなので意見があれば是非ご連絡ください!選定理由や細かい実装についての相談などもどしどしお待ちしてまーす^^


明日は cognitom さんの「 ES6 で書くRiot - Rollup編」です! Rollup も良さそうですよねぇ〜〜😋