Slide 1

Slide 1 text

Savkin先生から学んだ ぼくの考えた最強の Angularアプリアーキテクチャ 2017.6.23

Slide 2

Slide 2 text

Savkin先生? Viktor Savkinさん Angularコミット数No.1 説明不要

Slide 3

Slide 3 text

Managing State in Angular Applications https://blog.nrwl.io/managing-state-in-angular-applications-22b75ef5625f 曰く、 ● フロントエンドの状態管理は難しい ● 大きく分けて6つの状態に分類できる ● 状態の同期も難しいが、こういう実装ミスをしがち ● ngrxを使ってみるべき ↑すごい長い、構成としては 1. 状態の分類 2. よくある実装 3. リファクタその1 4. リファクタその2 なので1をちゃんと読んで 3,4流し読みでもいいかも

Slide 4

Slide 4 text

Agenda ● フロントエンドにおける6つの状態について ● その状態を管理するAngularでの実装案 ○ ngrxを使わないアーキテクチャ

Slide 5

Slide 5 text

フロントエンドにおける6つの状態 ● Server state ● Persistent state ● URL and router state ● Client state ● Transient client state ● Local UI state ○ SS, PS, URLS, CS, TCS, UISと略すかも

Slide 6

Slide 6 text

Server state, Persistent state ● Server state ○ サーバーが保存しているデータ ○ REST APIなどでフロントエンドに送信される ● Persistent state ○ フロントエンドで保存している Server state ○ Server stateのキャッシュと見なすこともできる ○ 楽観的更新のために PSだけ更新するケースもある

Slide 7

Slide 7 text

URL and router state, Client state ● URL and router state ○ 現在のURL ● Client state ○ クライアント側の状態のうち、サーバーに保存されないもの ○ 例: Todoリストから完了したものだけ表示するフィルター ○ (URLと同期すべき状態) ● URLSとCSは同期すべき

Slide 8

Slide 8 text

Transient client state, Local UI State ● クライアント側でURLに同期されない状態 ○ 例: Youtubeで動画の再生中にブラウザを閉じて、次開くとその再生時間から開く ○ localStorageとかCookieとかのServiceに状態管理を任せる ● UIに閉じた状態 ○ ツールチップが表示されている /表示されていないなど

Slide 9

Slide 9 text

Server state, Persistent stateの実装 ● 一つのXHRを行うサービスに閉じて実装する ○ XHRを実行するメソッドと、最新の値を保持しておく Subject ○ XHRの実行時に副作用として Subjectを更新する HttpService Server state Persistent state

Slide 10

Slide 10 text

URL and router state, Client stateの実装 Component this.router.navigatetoUrl('/todos?status=done’); フィルターをユーザーが操作 ngOnInit() { // ActivatedRoute でルーティングの変更を検知 this.route.params .subscribe((params: Params) => this.filterStatus = params['status']); } html

Slide 11

Slide 11 text

URL and router state, Client state + Persistent Stateの実装 Component this.router.navigatetoUrl('/todos?status=done’); フィルターをユーザーが操作 ngOnInit() { // ActivatedRoute でルーティングの変更を検知 this.route.params .map((params: Params) => params['status']) .switchMap(status => this.service.fetchTodos(status)) .subscribe(todos => this.todos = todos); } html フィルターがバックエンドへのリク エストに影響する場合

Slide 12

Slide 12 text

Transient client state, Local UI Stateの実装 ● Transient client stete ○ localStorageとかCookieとかのServiceに状態管理を任せる ● Local UI State ○ Componentの変数に状態を持つ Component LocalStorageService

Slide 13

Slide 13 text

HttpService Server state Persistent state Component this.router.navigatetoUrl('/todos?status=done’); Router フィルターをユーザーが操作 html LocalStorageService StoreService Local UI state URL and router state Client state Transient client state Local UI state Container/Smart Component HttpやRouterのObservableをこ ねこねして現在の状態を計算す る Component ✝最強のアーキテクチャ✝ 全体図 何かいい名前が欲しい Store...? 線が太い赤枠:状態のデータ を持っているところ

Slide 14

Slide 14 text

状態をいろんなところで保持しない ● 状態を色んな所に持つと同期が難しい ○ 例: Todo詳細コンポーネントで編集したデータを Todoリストコンポーネントに反映 ● 状態を持つ箇所を限定する ○ その状態は内部では Subjectで保持し、外部にはObservableとして公開する ○ 参考: https://tomastrajan.github.io/angular-model-pattern-example#/about ● 他の状態はObservableの計算で表現する

Slide 15

Slide 15 text

状態をいろんなところで保持しない 例: Todoの状態をPersistent, Transient client, URL and route stateから計算す る ● 状態のソースは全てObservable ● combineLatestを使って3つの状態 をくっつけて新しいObservableを作 る 動作確認してないので動かない嘘コードかも

Slide 16

Slide 16 text

まとめ ● Savkin状態管理理論の6つの状態 ● それをAngularで実装するアーキテクチャの案 ○ でもほとんどはAngularとして普通の作り ○ Subjectで状態を保持するのがあまり普通じゃないくらい? ○ 最強のアーキテクチャゆえにもちろん行ける気がしているのでとりあえずこれで行く ○ 進めてみて過ちに気づいたら素直に認めて反映していく、やっぱ ngrxにするなど