『ネコミミでもわかるシングルページアプリケーション』を読む
https://gyazo.com/356c4aa1380238440984ba4cefdefd28
タイトル
ネコミミでもわかるシングルページアプリケーション
著者
年
2019
リソース
写経用リポジトリ
実行環境
yarn 1.13.0
npx 6.8.0
react: 16.8.6
本の内容
読む際の注意
本書のコード中における...は省略を表すkadoyau.icon
はじめに
ストア(アプリ内で保持するインスタンス・配列)設計の難しさ
ページ間で引き継ぐ?破棄する?
ここは読む上で気になるところkadoyau.icon
1. 開発環境を整える
このときCRAのreact-scripts要求するeslintのバージョンとnpxを使って導入したバージョンが食い違って怒られる。対応は表示されるので、手順通りにyarn.lockを消してpackage.jsonからeslintを消して入れ直す。ようするにeslint自体を自分で入れることはできない。CRAに任せる code:zsh
The react-scripts package provided by Create React App requires a dependency:
"eslint": "^5.16.0"
Don't try to install it manually: your package manager does it automatically.
However, a different version of eslint was detected higher up in the tree:
CRAの設定がpackage.jsonに残っているが、優先度が低いので無視される
ESLintに従ってApp.tsxを修正する
yarn lint:jsの結果が少し違った
PrettierをESLintのエラーとして出力できるように設定する
PrettierをESLintのruleにするプラグイン
ESlintを実行する際に自動的にPrettierがかかるようになる
2. SPAの基礎とReact Hooks
概要
つくるもの
YouTube Data APIを利用した簡単なYouTubeクローンを作成する。おおむね次のようなプロセスで実施する
MVP
UI/UXの考慮
ストア設計/ページ遷移最適化
React Routerのルーティング
コンポーネント
code:zsh
RootPage # Page
└── RootTemplate # Template
├── SearchBar # organism
└── SearchList
Pages以下に各ページのコンポーネントを作成し、実装していく function componentに直接関数を定義するとレンダリングのたびに再描画されるが、useCallback()を使うとメモ化される
useEffect()のdocにもこういう事が書いてあるkadoyau.icon
経験のある JavaScript 開発者であれば、useEffect に渡される関数は毎回のレンダーごとに異なっているということに気付くかもしれません。これは意図的なものです。むしろ、そのようにすることで、古い値を参照してしまう心配なしに副作用関数内から count を読むことができるのです。
useCallbackとuseMemoの違い
評価された値が変えるかそうでないか
useCallback(fn, deps) は useMemo(() => fn, deps) と等価です
https://gyazo.com/478c083036108a854fe68ea577b08182
3. YouTube Data APIの利用と非同期通信
APIキーを作成し、用途の制限を設定する
process.envで取得する型はstring|undefinedなのを!でstringに限定
TypeScript 2から使える
A new ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms <T>x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.
環境変数の設定
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
公開するなら注意が必要
.env.localで.envを上書きできる
ここまで来るとこんな感じになる
https://gyazo.com/bf1a35bc419b232c751617a2e5538318
ListItemTextのstyleが図3.6と合っていないのはなぜ?
注意:API limitが10000 Query per dayなのでガチャ押ししていると意外と簡単に上限に達してしまうっぽい?
Chapter 4でdebounceを実装すればだいぶましになるはず
動画プレイヤーを表示させる
コンポーネントの階層
code:watch
WatchPage # Page
└── WatchTemplate # Template
├── WatchTitleBar # organism
├── WatchPlayer
└── WatchDetails
3.5 RootとWatchのつなぎ込み
historyオブジェクトが使いたいのでReactRouterの設定をする 3章が終わるとこんな感じになる
https://gyazo.com/da8f492d1af0474d42943813475b462d
4. SPAにおけるUI/UXの問題と解決
以下の利用上の不便を解決する
検索が1文字ごとに行われる
通信時のステータスがユーザにわからない
ブラウザバックしたときに検索結果が保存されない
4.1 debounceによる通信制御
ユーザの入力が終わったら検索したい
最終的な入力から一定時間入力が終わったとみなす
4.2 通信状態の表示
非同期に通信が走る際には通信中/通信失敗/通信完了をユーザにフィードバックしたい
vhを利用
Viewport単位と%との間には大きな違いがあります。%指定の場合、子要素の幅や高さは親要素の幅や高さに対して決定されます ロード中にローディングのアニメーションを出し、通信失敗したときにエラーを表示する
https://gyazo.com/767f10043c5e53f042e69807b9300c88
通信失敗させるために無理やり開発ツールでofflineにしたところ。失敗していることがわかる
その後にonlineにした際にAPIコール中は 。○。みたいなアニメーションがロード時に表示されている
検索結果が0のときのメッセージ表示もする
https://gyazo.com/323705995908c686e29a497042d5adfd
頭が悪そうな検索ワードにしないと検索結果が0件にならない
4.3 ブラウザバック対応
課題:ここまでの実装では、ブラウザバックしたときに検索結果が表示されない
https://gyazo.com/a0f07ac529e1ada9b2665c0fa786b590
目的:watchからrootにブラウザバックしたときに正常に動く(前回の検索結果を表示する)ようにする
手法:最も外のコンポーネントで定義されたStateを使って情報を保持する
こうなる
https://gyazo.com/55be656aa8bdad7a059518442f879686
5 SPAにおけるパフォーマンスの恒常
課題:ロード時間を短くしたい
変数の無駄な再定義をすくなくする
useContextによるpropsバケツリレー回避(中間コンポーネントのリレーをスキップするのでレンダリングが減るかもしれない) 無駄なレンダリングを少なくする
普通にやると、画面外の画像の読み込みが裏で行われる
画面に表示されてから行われるようにするのがlazy loading
lazysizesを使う。ただしChrome 75からブラウザの機能で実装されるようになる create-react-appで生成されるファイルはバンドルされた単一ファイルなので、でコンポーネントが多くなるとファイルサイズが大きくなる
SPAは訪問してないページのアプリケーションコードも読み込むので遅い
React.lazyとReact.Suspenseコンポーネントを使って実装する
code splitting 前
https://gyazo.com/a841349348ef23acb4812d6e5b76664c
ロード時に1.chunk.jsがロードされている
code splitting 後
https://gyazo.com/a6bcfe8c467dbe6a9b0d57543b2ef1b2
n.chunk.jsのうち必要なものだけがロードされているっぽい挙動をしている
通して困ったこと
IntelliJ IDEAがmodule.cssを認識してくれない(フルパスを手動で書かないといけない。書いた場合にcssを呼び出しコード上で参照する際には補完される)