フロントエンドエンジニアがSPAを開発する上で理解しておきたいこと

## はじめに
近年SPA（シングルページアプリケーション）で構築されているWebアプリケーションが増えてきていますが、
新人エンジニアで初めての開発がSPAのWebアプリケーションという場合も少なくないのではないでしょうか。

初めてのWeb開発がSPAでも問題はない（むしろ幸い？）ですが、
使われている技術・思想などを知らずに開発するのは効率が悪いと感じています。

この記事を読むことで、SPAを支える主要な技術や思想を理解していただき、
今後フロントエンドを開発する際の一助になればと思い書きました。

## 仮想DOM
SPAを構築するためのフレームワークは、
データの状態に対してリアクティブに画面を描画するために**仮想DOM**と呼ばれる技術を使っています。
したがって、SPA構築フレームワークを使ってWebページを作成するには根底にある仮想DOMを知っておく必要があります。
（そもそものDOMについての解説はこの記事では触れないので、[こちら](https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Introduction)等を参照してください）

SPAが登場する前は下記コードのように生のJavaScriptやjQueryで画面に表示されているDOMを直接操作し、
画面上に表示されている要素の見た目を動的に変更していました。

```js
// JavaScript
document.getElementById('target').checked = true;
// jQuery
$('#toggle').checked = true;
```

画面上のDOMの一つの色を切り替えるだけであればこれでも問題ないかもしれませんが、
動的に画面の見た目を大きく変更したい場合、DOMを直接操作するのでは
**・コードが煩雑になり可読性が悪い**
**・都度DOMを操作するとDOMが変更されるたびにブラウザ上でHTMLを解析してレンダリング（描画処理）が走り、効率が悪い**
という問題がありました。
この問題を解決するために仮想DOMという技術が生まれたのです！

仮想DOMの場合、リアルDOM（画面上に描画する元になるDOM）とは別に、
仮想DOM（リアルDOMとは別にDOMを表現するオブジェクト）をアプリケーション側で持ち、
動的にDOMを変更したい場合は仮想DOMを操作し、
最終的な仮想DOMとリアルDOMとの差分だけをリアルDOMに適用し、一度だけレンダリングが走るようになっています。
こうすることで効率的な画面への描画を行えるようになっています。
![1_hwlyMTnboUp9Mk0mUYhpdQ-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887131/b7741a02-04bf-6df6-ba5a-66577405a928.png)
引用元：https://medium.com/@koheimikami/understanding-rendering-process-with-virtual-dom-in-vue-js-a6e602811782

仮想DOMについて理解していなくてもSPAのアプリケーションを作成することはできますが、
難易度の高い課題にぶつかった際や高度なレベルでのパフォーマンス改善が必要な際に途方にくれることにならないよう、
きちんと理解しておきましょう！

## 状態管理
SPAを使ったWebアプリケーションを開発する場合、
状態管理に関連するコードを書くことがほとんどだと思います。
**「状態管理ってなぜ必要なの？めんどくさいだけじゃない？」**
と思ってしまう方もいるのではないでしょうか。
そんな方に向けて、状態管理がなぜ必要なのかを理解していただくため、
状態管理のありがたさを私なりに解説します。

前述の仮想DOMでも触れましたが、
SPAを構築するためのフレームワークが登場する前は、JavaScriptで直接DOMを操作するしかなかったので、
例えば、トグルボタンがONなのかOFFなのかを知るには直接DOMを参照するしかなく、
UIには状態を持つコンポーネントが多くあるにも関わらず、アプリケーション側でUIの状態を知る方法がありませんでした。

```js

document.getElementById("toggle").value //ON?OFF?
```

この問題を解決するため、SPAフレームワークではアプリケーション側で各UIなどの状態を表すオブジェクトが存在し、
今の状態を知るためには直接DOMを参照するのではなく、
この状態オブジェクトを参照し、これまでのフローとは逆に**状態オブジェクトの状態をDOMに反映すると**いうフローになっています。

今までもUIには確かに状態は存在していたのですが、アプリケーション側では状態を持っていなかったことにより、
複雑性・煩雑生が上がっていました。
アプリケーション側で状態をもつことにより、よりドメインロジックの実装に集中できるようになっています。

## Flux
Vue.jsやReact.jsでアプリケーションを構築する場合、
VuexやReduxなどの状態管理ライブラリを利用することがほとんどだと思います。
Vuex・ReduxはどちらもFluxという概念に基づいて設計されており、
状態の変更フローを単一方向にすることで、
状態が変更されるフローを追いやすくするような設計思想になっています。
![flux-simple-f8-diagram-with-client-action-1300w.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887131/61f4ff72-3d63-fa58-c31d-616292d47b1c.png)
引用元：https://github.com/facebook/flux/tree/master/examples/flux-concepts

上記の図がFluxのデータが更新されるフローで、各役割設計は下記のようになっています。

```
View: 画面
Action: データ変更処理の定義
Dispatcher: Actionを実行する
Store: 管理したいデータそのもの
```

Viewを起点にしてフローを説明すると、
**1. Storeにあるデータを変更するために、ActionをDispatcherに渡す**
**2. DispatcherがActionを実行し、Storeのデータを変更する**
**3. StoreのデータをViewに反映する**
のようなフローになります。
Fluxを理解していなければ「ActionとかDispatchとか何のためにやってんの？」って感じかもしれませんが、
ちゃんと理解して使うことで少しありがたみが出てくるのではないでしょうか！

## まとめ
これら以外にもSPAを開発する上で知っておかなければいけないことは数多くありますが、
初心者が抜け落ちがちになりそうなところに絞っています。

使っている技術の背景を知ることで、
開発効率を上げる・アウトプットの質を高めるというのもそうなのですが、
より楽しんで開発できると私自身は思っています！

記事に対するご意見・ご感想などありましたらコメント等いただけると幸いです。
## 参考
https://github.com/facebook/flux/tree/master/examples/flux-concepts
https://medium.com/@koheimikami/understanding-rendering-process-with-virtual-dom-in-vue-js-a6e602811782