Webフロントエンド基礎 後編(2/2) ~2022 日経 デジタル人材向け新卒研修より~

## 本記事の概要

- 本記事は筆者が、**日本経済新聞社**様の「2022年度 デジタル人材向け新卒研修 Webの基礎:後編」を読み、その内容が本当にわかりやすく勉強になったので、自分で改めて(色々省略しながら)書き起こしたものになります
- 内容を２つの記事に分けて投稿します(この記事は後編)

前編(1/2)はこちら↓

https://qiita.com/akitika/items/8a5b4492be5f79b80a1a

## 資料元情報

https://hack.nikkei.com/blog/training2022/

https://docs.google.com/presentation/d/e/2PACX-1vSjF1cp8fAdMKwFkLmtFT66e-UCD6zanO5KLsuRFmWyZ-8c06YQmgWT750Aqai2JfqHRARYWlkDLfaB/pub?slide=id.g122f21c424e_0_109

https://hack.nikkei.com/

## 目次

- Webサイトはどのようにして表示されるか?  ~~~ 前編(1/2) で記述します
- 伝統的な開発方法                　　　　　~~~
- SPAという考え方                    ~~~
- ReactJSは何を解決するか？   
- TypeScriptは何を解決するか？ 
- SSRは何を解決するか？ 
- CDNは何を解決するか？ 

# ReactJSは何を解決するか？

## ReactというSPA構築に便利なライブラリ

- UI構築のためのJSライブラリ
- JSXと言うHTMLに似た記法でUIを構築できる
- コンポーネント指向

## データからUIが決まる = 宣言的UI

- **UI = f(state) or UI = f(data)**
- データや状態をReactに渡すと、ReactがUIを構築してくれる
- 凄いところ：**データを更新すると自動でUIも更新**され、その**差分だけをレンダリング**してくれる = エコ
- `開発者がDOMの更新を頑張らなくても良い`
- `データの流し込みとJSXの定義さえすれば良い`

## パーツ単位でJSXを定義する

- パーツごとにJSXを定義できる
- 定義したコンポーネントは、HTMLのように呼び出せる
- テンプレートを用意して、親(呼び出し元)からデータを渡すことで、**異なるデータに対して同じスタイルでコンポーネントを呼び出せる**
- Webサイトをパーツの入れ子関係で捉えることができる

## コンポーネント・パーツを作るメリット

- 同じ構造のコンテンツは再利用できる
- 小さく作ることで、修正/編集のコスト・バグの調査コストが低くなる

## Reactを採用する嬉しさ

- JSX記法と宣言的UIにより、SPAを構築する際のDOM操作の考慮が要らなくなる
- コンポーネント・パーツ単位でのUI開発が可能になる

# TypeScriptは何を解決するか？

## 型とは

- 値の種類 = string, int, boolean, array, null, …
- 言語が提供している
- 独自の型もユーザーが定義できる
- 変数、引数、戻り値に対して、ラベルのように付与できる

## 型検査

- 型を持つプログラミング言語**(コンパイラ)は、型検査機能を持つ**
- 定義された変数や関数、それらに付与された型から矛盾を見つけ出せる
- 矛盾を見つけると、それは意図しない呼び出しをしたこと意味し、型検査をすることで`プログラムの実行前に誤りを知ることができる`
    - スタンダードなeditorは、editor上でも肩の矛盾を見つけることができるので、型検査前に矛盾に気づくことも可能

## 型をつけるメリット

- コードを変更して型検査が失敗するようになった時、バグを埋め込んだと気づくことができる
- もしくはそもそもコンパイルできないので、強制的に気付かされる
- 自分が実装に詳しくないコードの解読や実装に役立つ
    - 型情報はeditor上でドキュメントのように機能するから
    

## ReactとTypeScript

→ `堅牢なUIを作りやすくなった`

- 親から呼び出す、子コンポーネントに渡すデータの構造を検査できる
    - 存在しないデータを描画しようとすることによる、アプリケーションのクラッシュを防ぐことができる
- UIを構築するコードに型がつくことが画期的
    - HTMLやテンプレートエンジンには型が付けられなかった
    - Reactが登場するまでは、UIを作る処理(View層)が原因でアプリがクラッシュすることがあったが、React + TSの登場でその可能性を減らすことができた
    

## トランスパイラ

→ `ソースコードから型を削除する`

- **そもそもTypeScriptはブラウザで動かない**
- **JSX、TSX(JSXのTSバージョン)もブラウザで動かない**
- TS, TSX → JSに変換する仕組みを用意する
    - その変換の仕組みがトランスパイラ

## 代表的なトランスパイラ

- Babel
    - 様々なバージョンや種類のaltJSをJSに変換するツール
    - プラグインで変換を制御できる
    - 「TS → JS」「JSX → JS」の変換機能がサポートされている
- TSC
    - TSそれ自体のコンパイラであり、開発元のMicrosoftが作っている
    - 「TS → JS」「JSX → JS」の変換機能がサポートされている


# SSRは何を解決するか？

## SPAにはSPA特有の弱点がある

→ `全てがJSであること`

- OGP
- SEO
- ファイルサイズ

## OGP

- Open Graph Protcol
- Metaによる**social graphにおけるリッチ表現**
- OGPはHTML上のmetaタグを、SNSなどの各サービスのbotが解釈し表示される
- 多くの場合、**botが解釈するのはHTML**
- つまり`HTMLファイルにコンテンツを描画しないSPAでは、OGPが展開されない`

## SEO

- Googleは検索エンジンを動作させるために、各Webページにコンテンツを収集するためのbotを送る
- **クローラーが読み取るのはHTML**
- `HTMLが存在しないSPAではからコンテンツとして認識される`
    - botもJSを認識しようと頑張っているが、JS実行の待ち時間があるので、結局SPAはSEOが苦手

## ファイルサイズ

- SPAは、全ページのコンテンツが１つのページに収まっている
- そのためサイズがとても大きく、ブラウザでアクセスした際の読み込みコストが大きい
- 例えば、`トップページを表示するためだけに、結果として他のページのコンテンツの読み込みも行っている`ということであり、本来であれば**その時点でユーザーに表示しないページのデータの読み込みは不要**

## SSRで解決できる

→ `SPAとHTMLのいいとこ取り`

- Server Side Rendering
- あるページを表示する際、**`サーバーサイドでそのページに必要なHTMLをSPAのコンポーネントを元に生成`**し、HTMLファイルとSPA用のJSファイルを返す
- 受け取ったHTMLファイルを表示すると、ユーザーがアクセスしたURLのコンテンツを表示でき、**表示のために全コンテンツを返す必要がなくなってエコ**
- その**HTML上でSPAとしてのJSファイルを読み込む**ことで、**次の遷移からはSPAとして動作**できる

## SSRの弱点

- 実装が大変
    - **サーバーでReactを実行する仕組みが必要**。多くの場合、NodeJSのサーバーが必要になる
    - ただ最近では、この辺りを楽に作ることができるNextJSというライブラリを使えば実装も楽
- API特性によってはSPAより表示が遅くなる
    - サーバーでのデータ取得などに時間がかかると、HTMLの生成にも時間がかかる
    - SPAはコンテンツが埋め込まれていない以上、HTMLだけはすぐに返せるので、HTMLの到着時間はSPAの方が早くなる

# CDNは何を解決するか？

## キャッシュの考え方

2回目のリクエストに対するレスポンスが、1回目のレスポンスと同じであれば、1回目のレスポンス結果を保持しておきそれを返せば、サーバーやデータベースの処理が不要になる

## キャッシュとは

- 過去に一度読み込んだもの、またはそれを保持しているもの
- もう一度、同じものを読み込もうとした場合に、代わりにキャッシュを返すことでリクエストが不要になり、パフォーマンスが向上する

## キャッシュを保持する主体

- ブラウザ
    - ユーザーのクライアントでキャッシュを持てば、サーバーへリクエストすることなくデータを得ることが可能
- サーバー
    - DBのアクセス結果やレスポンス作成結果をキャッシュすることで、そのような処理をスキップできる
    - サーバー上のメモリや、Redisといった製品が使われる
- CDN
    - 通信の経路上にキャッシュする
    - 詳しくは後述

## 危険なキャッシュ

- キャッシュはその時点では最新のデータではない
    - 例えば記事データをキャッシュしていて、記事を更新したときにキャッシュを返すと、更新前の記事を返すことになる
- キャッシュの中に個人情報を含めてしまうと個人情報漏洩になる
    - 前の人のアクセス結果を、次にアクセスした人が取得するため

## CDN

- Content Delivery Network
- ユーザーとサーバーの中間に置ける代理サーバー
    - このとき元々あったサーバーのことは区別のため**オリジンサーバー**と呼ばれる
- リクエストされたURLに対するキャッシュを保持できる

## CDNの嬉しいこと

クライアントとオリジンサーバーの中間にあるCDNが、代わりにレスポンスを返すため… ↓

- オリジンサーバーへのアクセス負荷を軽減できる
- キャッシュが使える
    - 製品や実装によっては、Cache-Controlを使った制御が可能
    - 製品や実装によっては、keyを指定してcacheの削除が可能
- キャッシュ機能に限らず、`中継するRequestやResponseの内容そのものに介入`できていろいろなことができる
    - リクエストヘッダのパース、検証
    - クエリパラメータの付与
    

## Cache-Control

- 詳しくは[Cache-Control - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control) を参照
- ResuponseのHTTP Headerに付与できる
- これを受け取ったブラウザやCDNは、そこに書かれてある通りにキャッシュをコントロールする
    - 例えば、キャッシュに制限時間を設けて、あるデータが古くないキャッシュであることを一定期間保証することができる

## Fastly

- 日経が契約しているCDNサービス
- Cacheの**Purge(削除)**が非常に高速
- 柔軟なCache-Controlをサポート
    - HTTP Headerや各種プログラミング言語で柔軟にカスタマイズできる
    

## SSRとCDN

`SSRのデメリットはCDNで解消できることがある`

- 仮に**SSRに時間がかかったとしても、その生成結果であるHTMLをキャッシュしておけば**、`初回アクセス以外ではHTML生成過程を踏まずにHTMLを返せる`ようになるから
- ただし、その恩恵を得るためにはキャッシュをhitさせる必要があり、cache controlや設計を頑張らないといけない
- そのため、日経ではその設計やCDNコントロールに気合が入っている

# 改めて結論

- 電子版の初期実装ではテンプレートエンジンを採用していた
- ある時から開発効率・体験を向上させるためにReactを取り入れていた
- 日経ではメディア開発という特性上、SEOとOGP対応が必須であり、SSRを採用している
- SSRのデメリットを解消するためにCDNを採用している