angularjsとfluxとriotjsと

Post on 22-Jan-2018

4.054 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

AngularJSとFluxとRiotJSと

2015/10/28 GotandaJS # @mizuki_r

Profileaccount.

twitter: @mizuki_r github: ry_mizuki role.

フロントエンドエンジニア

tags.

AngularJS, RiotJS, Backbone,

hariko, angular-period, etc

Theme

• AngularJSで書いたアプリをFlux化した話

• Flux化したAngularJSアプリにRiotJS入れた話

AngularJSで書いたアプリをFlux化した話

What is Flux?

Flux’s architecture

https://facebook.github.io/flux/docs/overview.html

Flux’s architecture

• Facebookが提唱したアーキテクチャ

• データの流れを一方向に限定する

• Store, View, Dispatcherの責務がActionという単位で処理を回す

Flux’s architecture

https://github.com/facebook/flux/tree/master/examples/flux-todomvc/#structure-and-data-flow

Why Flux

Why Flux?• modelの管理に疲れた

• データ構造と責務分担の分類の考察

• 急なデータの変更、Viewの変更

• controllerでmodelを管理しがち

• modelとmodelの連携

• controllerの抽象化が雑に…

所謂MVCの運用には 高度な訓練と

高い意識が必要なのでは?

もっと低意識で運用したい!

I thought…

ぼくのかんがえたさいきょうの…• Dispatcherは自前でObserver定義 • ViewとActionCreator, Storeは一対

• ドメインの定義はViewにすべて移譲 • ActionCreatorは外部との連絡用

• API通信はngResourceをwrapしてrepositoryとして分離

• actionにする前にデータ整形を行うメソッドをかます

ぼくさいFlux arch

ぼくさいFlux arch

import * as action_creator from '../action-creators/example' import store from '../stores/example'

class ExampleCtrl { constructor ($scope) { this.onReceiveData = this.onReceiveData.bind(this) this.onDestroy = this.onDestroy.bind(this) store.addReceiveDataListener(this.onReceiveData) $scope.$on('$destroy', this.onDestroy) action_creator.init() } select () { action_creator.select() } onReceiveData () { this.data = store.getData() } onDestroy () { store.removeReceiveDataListener(this.onReceiveData) } }

angular.module('example').controller('ExampleCtrl', ExampleCtrl)

import dispatcher from '../dispatcher' import action_types from '../action-types' import injector from '../injector'

export function init () { dispatcher.handleViewAction({ type: action_types.INIT_EXAMPLE_VIEW, }) var Repository = injector.get('ExampleRepository') Repository.fetch().then((data) => { dispatcher.handleApiAction({ type: action_types.RECEIVE_EXAMPLE_DATA, data }) }) }

export function select () { dispatcher.handleViewAction({ type: action_types.SELECT_EXAMPLE_VIEW, }) var Repository = injector.get('ExampleRepository') Repository.post().then((data) => { dispatcher.handleApiAction({ type: action_types.POST_SELECT_EXAMPLE_DATA, data }) }) }

conclusion

• ViewをActionCreatorとStoreに抽象化できた

• コードが冗長になり、量が増えた

• 初期開発コストは高いが更新の手間などは減った

ViewをActionCreatorとStoreに抽象化できた

…あれ?

Angularじゃなくてもよくね?

Flux化したAngularJSアプリにRiotJS入れた話

What is RiotJS?

RiotJS

• Reactライクのユーザインタフェースライブラリ

• とっても小さい

• Virtual-DOM

• JavaScript in HTML

<todo>

<!-- layout --> <h3>{ opts.title }</h3>

<ul> <li each={ item, i in items }>{ item }</li> </ul>

<form onsubmit={ add }> <input> <button>Add #{ items.length + 1 }</button> </form>

<!-- logic --> <script> this.items = []

add(e) { var input = e.target[0] this.items.push(input.value) input.value = '' } </script>

</todo>

http://riotjs.com/ja/

ファイルサイズ

Reactの約1/19!

つまり…• 小さいし必要最小限の機能

• 細かいViewの制御なら十分なAPI

• 明示的な更新が可能なI/F

• Component系なので最小限の変更範囲

• 書きやすそうなJSX

Why is RiotJS?

AngularJSへの不満…

• $applyが重い

• 暗黙的な$digestの管理が辛い

$applyが遅い• 式を受け取りViewを更新するかを判定

• 更新する場合は`$scope.$digest()` を実行

• $http, $timeoutなどのAPIが内部的に利用

• 登録されているすべてのリスナを評価する

• 遅い評価式を登録してしまうと更新のたびに…

暗黙的な$digestが辛い• $http, $timeoutなどAPIが暗黙的に発行する

• 発行しないAPIもある

• 自前で作った機能は$scope.$apply等が必要

• たまたまうまく更新がされるケース

• digest中にdigestを発行すると死ぬ

つまり…• 特定のView以下で更新したい

• 短いサイクルでの更新

• 毎秒すべてのViewを評価してどうする

• 明示的に更新したい

• 必要ないところで評価されても

• 更新したいタイミングは僕らが決めたい

Angular with Riot

RiotJSの役割• 末端のViewの更新サイクルの管理

• 毎秒更新が発生するもの

• ホバーなどサイクルが短いもの

• ユーザアクションのハンドルと他のViewとの連携はFluxベースのアーキテクチャで吸収

• RiotからAngularのViewは参照しない

directive

angular.module('example', []).directive('todo', function () { return function () { riot.mount('todo') } })

directive化することで、templateから参照できる。

outside injector

exports.get = function (name) { return angular.element(document).injector().get(name) }

injectorをAngularの管理外から参照できるように

入れてみた結果• 「遅い」と言われてた部分が解消(体感的に)

• ぶっちゃけRiotJSが早いわけじゃない

• むしろ状況次第ではAngularより遅い

• $digest漏れや$applyの遅延による「遅く見える」が減少した

• RiotJS、以外と書きやすい

Conclusion

Conclusion• FluxによるViewの抽象化事例を紹介

• Viewの単位でコードを管理できるので、追加・更新・削除が思いの外簡単になった

• でもコード量は増えた

• AngularJSとRiotJSの共存事例を紹介

• 目に見えて反応が違った

• RiotJSは必要最小限で使う分にはかなり使い勝手良い

• 個人的にはRiotJSXはもっと使って行きたい

Next Generation• Fluxでの責務分担のあり方をもうちょっと考えたい

• いずれこれは二層式に集約されていくのだろうなと

• ServiceWorker上で扱えるレベルのロジックの抽象化

• メインスレッドを綺麗にしてUIのパフォーマンスあげたい

ご清聴ありがとうございました

top related