現実世界のNext.js

![20220326_nextjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/f3c39cfa-383e-281f-7e82-c6d8de9339f3.png)
# 初めに
- Next.js入門書の学習まとめです
    - 簡素に書いています。キーワードを拾ってググるきっかけとして使ってもらえればと思います

## 対象書籍「Real-World Next.js (現実世界のNext.js)」

https://learning.oreilly.com/library/view/real-world-next-js/9781801073493/

- 概要
    - **Next.js入門書** 。入門書然としており、重要な内容をサラッと説明する感じ
    - 対象レベルはReact初級者程度
    - **2022年2月リリース** なのでそこそこの鮮度があるはず
    - オライリー電子書籍読み放題(ACM特典）で読めるNext.jsの本は少ないのでありがたいです
- 【書籍構成】
  - パート1 第1～3章 Next.jsの機能紹介
  - パート2 第4～11章 各機能のNext.jsでの実装方法の紹介
    - 8章以降は読み飛ばしています
  - パート3 第12～13章 Webアプリ例
    - 特に興味なかったので読み飛ばしています
  - 第14章 まとめ
- [書籍公式GitHubリポジトリ](https://github.com/PacktPublishing/Real-World-Next.js)

# まとめ

## 第1章「Next.jsの簡単な紹介」
- [公式リポジトリコード](https://github.com/PacktPublishing/Real-World-Next.js/tree/main/01-a-brief-introduction-to-nextjs)
- [Next.jsと他のフレームワークとの比較記事](https://kentico.jp/kontent/blog/gatsby-vs-next-gridsome-nuxt)などでよく書かれていることと大きく違わないためスキップ
## 第2章「レンダリング戦略」
- [公式リポジトリコード](https://github.com/PacktPublishing/Real-World-Next.js/tree/main/02-different-rendering-strategies)
- 【概要】SSR/CSR/SSG(ISR含む)の簡単な記述例を紹介
- SSR
  - 【利点】レンダリングのコストがサーバー側に移るので「セキュリティ/互換性/レスポンス」の面で有利
  - 【欠点】サーバー側にWebアプリを要実装／レンダリングするのでさすがにSSGよりは遅い
  - Next.jsはデフォルトだと静的ページになる
  - 【SSRの使い方】getServerSideProps()というasync関数をexportするとこのページがプリレンダーされるようになる
    - 関数の返り値をページのコンポーネント内で使える
- CSR
  - 普通のReact
- SSG
  - ビルド時に生成される静的ページ
  - それだと使い勝手が悪いのでNext.jsではISR(Incremental ~)を採用
    - revalidate時間を決め、その時間を過ぎてから最初のリクエストで再レンダリング
## 第3章「Next.jsの基本とビルトインコンポーネント」
- [公式リポジトリコード](https://github.com/PacktPublishing/Real-World-Next.js/tree/main/03-next-js-basics-and-built-in-components) 
- コンポーネントファイルの配置を基に自動でルーティング
- ルートパラメータはファイル名を[～]とすることで設定可能(例：[name].js)
  - getServerSidePropsで取得してprops経由で渡す方法とuseRouterを使う方法あり
    - 処理時間かかる内容でもないので、後者の方が楽そう
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/be2e02d8-90b8-0168-9d4b-728037eaf3d5.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/c53fafd0-5f8e-70b1-b898-cfada022c7c9.png)
- useRouterでは上記ルートパラメータとクエリパラメータが同じuseRouter()結果に格納される。同じ名前の場合はルートパラメータが優先される
- <Link>コンポーネント(aタブの代わり)。デフォルトだとプリロードが有効。無効にするには `preload={false}` を指定する
![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/c705897e-9c57-e04b-9827-be05385fc0f2.jpeg)
- [リダイレクトを行う場合はいくつか方法あり](https://zenn.dev/uttk/articles/4649e49f1e6628)
    - 最初はuseEffect使うのが楽そう
    - ページの遷移はrouter.pushとrouter.replaceの両方で行えるが、ページ履歴にリダイレクト前のページが残るかどうかの違い（push:残る, replace:残らない）
- 静的ファイルの扱い
  - /public/に配置すると自動で静的ファイルとしてみなしてアクセス可能
- [CLS](https://qiita.com/tora_oba/items/3db1dc072379b327054b)対策
  - 画像を埋め込む場合、標準の<image />で画像を埋め込むとCLS(ローディング前後の位置ずれ)が発生しSEO的に不利
  - Next.jsでは独自画像コンポーネント<Image />が用意されておりCLS対策済
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/70dc1d82-4f02-eb77-e6c5-62ad45bcdf40.png)
- [＜Image＞コンポーネントのlayoutプロパティ](https://nextjs.org/docs/api-reference/next/image#layout)で画像の引き延ばし設定を変更可能(fixed:固定サイズ、responsive:デバイス横幅に合わせて調整 等)
- メタ情報
  - <Head>コンポーネントを使う
    - コンポーネント化して複数ページで使う回すのが一般的
- [_app.js](https://nextjs.org/docs/advanced-features/custom-app)
  - 全ページ共通で表示するコンテンツを定義(ナビゲーションバー等)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/09fbf376-a608-b422-8ab3-c2580e36821b.png)
- [ _documen.js ](https://nextjs.org/docs/advanced-features/custom-document)
  - <html>や<body>タグのつくりをカスタマイズ可能
  - 4種のコンポーネントを使用(どれも抜けてはいけない）
    1. <Html>⇒<html>タグ(lang等の設定)
    2. <Head>⇒これまで見てきた<Head>とは別物（動作はほぼ同じ）
    3. <Main>⇒ページコンポネント
    4. <NextScript>⇒カスタムスクリプト
    - サーバー側の処理(getServerSideProps等)は実装不可
# パート2「ハンズオン」
- パート1（～3章）はNext.jsの個別要素を紹介してきた
- パート2（4~11章）では特定のトピックのNext.jsでの実現法を紹介する
  - **通常のフロントエンドでの実装方法と同じ内容を説明している箇所が多々あり**
    - 「Next.jsで実装するなら～」という趣旨なので、必ずしもNext.js独自の手法というわけではない
  - 各章トピック
  4.「APIを叩く」
  5.「状態管理」
  6.「CSS」
  7.「UIフレームワーク」
  8.「カスタムサーバ」
  9.「テスト」
  10.「SEO・性能」
  11.「展開先」
## 第4章「データ取得」
- [公式リポジトリコード](https://github.com/PacktPublishing/Real-World-Next.js/tree/main/04-nextjs-data-flow) 
- 環境準備
  - create-next-appの環境に[Atomic Design](https://design.dena.com/design/atomic-design-%E3%82%92%E5%88%86%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A4%E3%82%82%E3%82%8A%E3%81%AB%E3%81%AA%E3%82%8B)用にコンポーネントフォルダを作成
  - コンポーネントをexportしない汎用スクリプトはユーティリティとしてフォルダを分ける(テストファイル
*.test.jsも作っておく)
  - /publicフォルダ配下にデータ種別フォルダ(css,js等)と[manifest.json](https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/manifest.json)を作成
  - CSS：標準的な方法はない(6,7章でCSSとUIフレームワークについて扱う)
  - 3rdパーティライブラリ用ラッパースクリプトは/libフォルダ配下に置く
  - 準備終了後フォルダ構成
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/1372e3c4-c69d-4b07-31c5-73ae127569c6.png)
- データ取得
  - Next.jsはバックエンド機能があるのでDB/ファイルシステム等にアクセス可能
    - ただ、セキュリティ的に問題あり。フロントエンドエンジンらしくAPI経由でのアクセス推奨
- サーバー側からのAPIアクセス方法は2種
    1. Node.jsの　httpライブラリ
    2. 3rdパーティ　　〃
  - [一般] APIの主な認証手段 Oauth2.0 / JWT / APIキー
  - 例：axiosでRest API発行(ヘッダにAPIトークンを載せる。トークンは.envで管理)
- クライアント側
  - 普通のフロントエンドと同じ（fetch APIやaxios等を使う）
  - 2つ問題あり「CORS」「トークンがオープンになる」
  - 対策：APIルートの新設
    - [/pages/api/内の全ファイルはNext.jsによってAPIルートとみなされる](https://zenn.dev/terrierscript/books/2020-09-next-js/viewer/1-5#api%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B)
- GraphQL 
  - 普通に[Apollo](https://www.apollographql.com/)を使う
  - インストールパッケージ：@apollo/client graphql isomorphic-unfetch
    - isomorphic-unfetch：fetchAPIのポリフィル用
  - [libフォルダ内にApolloクライアントコードを追加](https://github.com/PacktPublishing/Real-World-Next.js/blob/main/04-nextjs-data-flow/signbook/lib/apollo/index.js)
    - サーバー/クライアント両対応(上記コードだと変数windowで切り替え)
    - Apolloの初期化は時間がかかるのでuseMemo()でメモ化しておく
  - GraphQLの[mutation](https://graphql.org/learn/queries/)をApolloで使うには[useMutation()](https://apollographql.com/docs/react/data/mutations/)を使う
## 第5章「状態管理」
- Next.jsの状態管理はReact同様コンテキストAPIやReduxで管理する
- コンテキストAPI：useState()を使う。_app.jsに入れ込むことで全ページ共通の状態管理が可能に(当然useContext()でもOK）
- [Redux](https://zenn.dev/jojo/articles/25c10b27783093)
  - 追加ライブラリ：reduxreact-redux (release) とredux-devtools-extension (dev)
  - /redux/フォルダ作成（reducerを書いたスクリプトを置く）
  - ストア(reducer+state)はcreateState()で作る
## 第6章「CSSと組み込みスタイリング方法」
- Node.jsでのCSSの基本的な使い方を紹介する
- [Styled-JSX](https://github.com/vercel/styled-jsx)
  - <style jsx>{`CSS表記`}</style> ⇒ 書いたコンポーネントに適用
  - <style jsx global>{`CSS表記`}</style> ⇒  全コンポーネントに適用
- [CSS modules](https://zenn.dev/catnose99/scraps/5e3d51d75113d3)
  - Styled-JSXだとIDE対応が不十分かつパフォーマンスに難あり
  - CSS modulesは「プレーンなCSS表記」＋「パフォーマンスオーバーヘッド無し」
  - スクリプト同様にimportして使える
     - 重複しないクラス名が自動的に割り当てられる
  - グローバル適用するには:globalを追加
  - 他のルールを継承(?)して拡張したい場合は composes:
  - CSS modulesはNext.jsに追加インストール不要で即使用可能
- [SASS](https://nextjs.org/docs/basic-features/built-in-css-support#sass-support)
  - 追加：sass (release)
  - CSS modulesでSASS/SCSS文法利用可能に
## 第7章「UIフレームワークの使用」
- 使うUIライブラリはReactと同等(Chakra UI / TailwindCSS / ヘッドレスUI等)
- [Chakra UI](https://chakra-ui.com/guides/getting-started/nextjs-guide)
  - 追加：@chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6  @chakra-ui/icons
  - _app.js内でページコンポーネントを<ChakraProvider>でラップする
  - 既存のテーマをオーバーライドするにはextendTheme()をインポートして指定
  - [カラーモード対応](https://chakra-ui.com/docs/styled-system/features/color-mode)(ダークモード等)も_document.jsに少し変更を加える事で対応可能
- [TailwindCSS](https://tailwindcss.com/docs/guides/nextjs)
  - 概要：CSSルールの追加だけなので **フレームワーク非依存**
  - 追加(dev)：autoprefixer postcss tailwindcss
  - tailwind.config.js：テーマやダークモード等の設定が行える
  - postcss.config.js：内部で使用しているPostCSSの設定が行える
  - _app.js内でページコンポーネントを<ThemeProvider>でラップ
- [Headless UI](https://headlessui.dev)
  - TailwindCSSを補間するような形でCSSスタイルのない動的コンポーネントのみを提供（TailwindCSS非依存）
    - 作っているのはTailwindCSSと同じ組織
## 第8章「カスタムサーバー」
- Next.jsのバックエンドをExpress.jsやFastifyサーバと一緒に運用する方法について
- スキップ
## 第9章「テスト」
- Next.jsのテストは特に特別なことはなし(Jest/CypressやReact Testing Libraryを使用
- [別の本](https://learning.oreilly.com/library/view/test-driven-development-with/9781484269725/)を読む予定なのでスキップ
## 第10章「SEO対策」
- Next.js自体がSEOに対して特別な事はなし
- ただ、第2章で述べたようにNext.jsはCSR/SSR/SSGを組み合わせでSEO対策が可能
- また、パフォーマンス評価用の組み込み関数[reportWebVitals()](https://zenn.dev/uttk/scraps/f67550053d9f16)がある（Googleと共同開発）
  - Vercelにデプロイするとダッシュボードが提供される
## 第11章「様々な環境へのデプロイ」
- Next.jsアプリのデプロイ方法(Vercel／CDN(静的サイト)／その他(各種PaaS)／コンテナ化)が軽く紹介されている
- 特質すべき内容無し。スキップ
# パート3
## 第12~13章「アプリ例」
- 実際のアプリに近い例（外部サービスの利用等）を紹介
- あまり興味がないのでスキップ
## 第14章「次の学習のためのガイド」
- これまでのまとめと次に学習すべきことについて
- 習作アプリ向けテーマ
  - ストリーミングウェブサイト
  - ブログプラットフォーム
  - リアルタイムチャットウェブサイト
- 追加の学習すべきこと
  - TypeScript／Webpack設定方法／レンダリング戦略等

# 最後に(読み終わった後での感想）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406339/03781f2e-d2b6-5d7e-151d-5defc855de7a.png)
- 読んでて思ったことは「 **必要な情報は公式ドキュメント・チュートリアルに大体載ってるな** 」という事です
- 本書は「重要な内容をシンプルに説明」というスタンスを取っていますが、これが公式チュートリアルと重複してしまっており、比較したときに「ほぼ同じ内容じゃないかよ」と感じることが何回かありました
- とはいえ、本書籍独自の内容も当然ありますし、コンテンツの形式との違いや公式視点・第三者視点での違いなどもあり、どちらを好むかは人それぞれかと思います
    - 本書でNext.jsの基本を学べたことは間違いありません。2022年3月現在でそこそこおススメの書籍です（公式ドキュメント・チュートリアルもおすすめです）