当サイトはPR広告を利用しています。

チュートリアル Learn Next.jsで学べる内容まとめ

2024年1月30日

Next.jsのコア機能を学ぶことができるチュートリアルとして「Learn Next.js」が存在します。

このチュートリアルは全16チャプターもあり、かつそれぞれのチャプターの文量も多いため本記事ではLearn Next.jsで学べる内容を要約して箇条書きでまとめます。

この記事の使い方は以下の通りです。

  • あなたがチュートリアル実施前の場合:チュートリアルを通して何が学べるのか概要を知る
  • あなたがチュートリアル実施後の場合:チュートリアルで学んだ内容のおさらい

できるだけ噛み砕いた文章にしているので、チュートリアルを進める中でよく理解できない部分があったら確認のために本記事を見ていただく形も有用かと思います。

また読者はReactについて基本的な知識がある状態を想定しています。Reactについてあまり詳しくない場合は「React Foundations」で事前に学んでおく必要があります。Learn Next.jsでもReactの学習用にこのサイトを勧めていましたのでまだ実施してない方はぜひ。

Introduction

  • Next.jsはReactをベースにしたフレームワーク
    • React自体はフレームワークではなくライブラリである。機能が豊富すぎるためにフレームワークのような印象もある。しかし実はただのjavascriptライブラリという扱い。
  • Learn Next.jsではJavaScriptではなく、TypeScriptを利用する

Chapter1 Getting Started

  • “create-next-app"というコマンドでNext.jsアプリの雛形を作成可能
  • “npm i"でpackage.jsonに記載されたライブラリをインストール
  • “npm run dev"で開発環境用Next.jsサーバーを起動

Chapter2 CSS Styling

  • /app/layout.tsxでcssファイルをインポートするとすべてのページに対して適用されるcssとなる
  • CSSフレームワークであるTailwindを利用すると外観を簡単にいい感じにしてくれる
    • Tailwindで定義されたクラスをTSX内の要素に追加するだけでOK
  • CSS modulesという装飾方法もある
    • cssファイルをモジュールとして扱うことで、別のCSSファイルとの名前の被りなどを気にしなくてもOKになるメリットをもたらしてくれる
  • Next.jsで最も利用されるCSSはTailwindとCSS modulesの二つ
  • 条件によってスタイルを変更したい場合はclsxライブラリを利用する

Chapter3 Optimizing Fonts and Images

  • フォントを最適な形で適用するためにはnext/fontが便利
    • 普通フォントを変更するのであればレンダリング時にネットワーク越しにダウンロードが必要でパフォーマンスに影響が生まれるが、next/fontという機能を利用するとローカルでのビルド時にダウンロードが完了し、静的ファイルとして公開する形になるので、パフォーマンスに影響がない形で任意のフォントを利用できる
    • app/layout.tsx内のbody要素に適用したいフォントを設定すれば、すべてのページにわたってそのフォントが設定される
  • 画像を最適な形で利用するにはnext/imageが便利
    • 便利なポイントは以下4つ
      • レイアウトシフトをしないようにできる
      • デバイスによって自動で画像サイズを最適化してくれる
      • デフォルトで遅延読み込み設定
      • 最適なフォーマットでの自動提供(WebPやAVIF)

Chapter4 Creating Layouts and Pages

  • Next.jsはフォルダ構成がアプリケーションページへのパスと対応している
  • page.tsx:各ページのメイン部分になるコンポーネントを定義するファイル。
    • 配置ディレクトリがそのままパスになる
      • プロジェクト作成時に自動で作成されるappフォルダの直下にpage.tsxを作ればサイトのルートページ
      • app/dashboardフォルダの中にpage.tsxを作ったら/dashboardにアクセスした時に表示されるページ
    • ユーザーが唯一アクセス可能なファイル(その他のファイルはあくまで参照されるファイル)
  • layout.tsx:同階層以下のページに対するレイアウトを決定するファイル
    • 内部的には同階層以下のファイルがlayout.tsxから呼ばれた後の結果を画面表示する形
    • appフォルダ直下のlayout.tsxはすべてのページに対して効力を持つレイアウトファイルで作成必須
      • 基本的にhtmlタグとbodyタグの要素を決定する。(他にメタデータも設定)
    • コンポーネントが分かれていることで画面変更時にレイアウト決定部分はレンダリングをしないようにできる(partial rendering)

Chapter5 Navigating Between Pages

  • ページ内のリンクはnext/linkのLinkコンポーネントを利用することで最適化される
    • aタグでのリンクだとページを切り替えるごとにページがフルでリフレッシュされるためパフォーマンスが悪い
    • 現在表示されているページにあるLinkの先のページはロードが開始するため、リンクをクリックしたタイミングでは即座に遷移できる
  • 今いるパスの名称はusePathnameフックを利用すれば取得できる
    • これを利用して現在のページを示すナビゲーション上のボタンの見た目を特徴づけることが可能(clsxも併せて利用)
  • 同じjsファイルでもクライアント用のファイルとサーバー用のファイルは明確に分かれており、利用できるメソッドも変わる
    • フックはクライアントサイドでしか利用不可
    • 例:useStateフックはクライアントサイドのコードでのみ利用可能

Chapter6 Setting Up Your Database

  • vercelというサイトを利用すると個人利用に限りNext.jsのアプリケーションをデプロイ可能→ウェブアプリとして世の中に公開できる
  • githubにアップロードしているリポジトリを簡単にvercelにデプロイしてプロジェクト化できる
  • vercelではデータベースを作成できる
    • 同時に認証用の情報も出力されるからその認証情報を利用してvercel上のプロジェクトから接続できる
    • ローカルには.envファイルに認証情報を記載するが、秘密情報のためgitignoreファイルを利用してgithubにはアップロードされないように注意する

Chapter7 Fetching Data

  • データベースからデータを取得するためには以下の3つの方法がある
    • API layer:クライアントからの依頼を受けてデータベースから値を取得するためのAPIを利用する
    • Database queries:SQLやORMを利用してサーバーサイドからデータベースに問い合わせする
      • API layerとは異なり、APIを利用する必要性はない
  • Next.jsはデフォルトではサーバーサイドでのデータ取得を行う(API作成は不要)
  • vercelのPostgreSQLを利用しているならvercel/postgresというSDKを利用すると簡単にSQLでの問い合わせが可能
    • sql関数を利用
  • Promise.all()メソッドを利用すると実行したい複数の関数を並列で実行することが可能

Chapter8 Static and Dynamic Rendering

  • キャッシュが保存されることでサーバー側の負荷を減らせたり、即座のページ表示が可能になる一方、頻繁に同一画面の情報がアップデートされるようなWebアプリケーションにはフィットしない
  • Dynamic Renderlingを利用するとリクエストのたびにサーバーサイドでのレンダリングを実行するようになる
    • next/cacheのunstable_noStoreを利用すると設定可能

Chapter9 Streaming

  • Streamingはデータ変換テクニックであり、1ページ上のUIを"チャンク"として分け、表示の準備ができたチャンクから順に表示させるもの
    • これを利用しない場合は、1ページ上のすべてのUIの表示準備が終わらないと画面全体が表示されない
    • Streamingを利用するには以下の2つの方法がある
      • loading.tsx:1ファイル全体に影響
      • <Suspense>コンポーネント:コンポーネントごとに適用可能
  • ()で挟んだフォルダーネームはURL名には影響せず、ロジカルグループとしてのフォルダーを作ることができる。(Route Groupsというらしい)
    • 例えばapp/dashboard/(overview)の下にlayout.tsxを配置した時には、app/dashboardにアクセスした時にlayout.tsxが効くが、app/dashboard/invoicesのようなさらに下のページには効かないようにできる
  • Streamingは過度に細かく設定すると画面の色々な箇所が徐々に更新されてユーザーにとって目障りになりかねない。これを防ぐためにコンポーネントをグループ化するコンポーネントを作り、それをSuspendさせる方法が良い

Chapter10 Partial Prerendering (Optional)

  • Partial Prerenderingは「一部のUIを静的に、一部のUIを動的にする」ための実験的な機能
  • Linkに記載されたパスのページはプリレンダリングされるが、noStoreを利用することでコンポーネントをdynamicにしたコンポーネントをSuspenseコンポーネントでラップするだけでNext.jsが勝手に動的なコンポーネントであると判断してくれて、リンクをクリックしたタイミングでのレンダリングを実行してくれる

Chapter11 Adding Search and Pagination

  • URLに検索ワードを含めることにはいくつかの利点がある
    • ブックマークにでき、共有可能になる
    • サーバーサイドに直接渡すことができ、サーバーサイドでのレンダリングを楽にする
    • アナリティクスやトラッキングに利用できる
  • Next.jsには検索機能を容易に実装可能にするフックが複数ある
    • useSearchParams:URLにある検索用パラメータを取得できる
    • usePathname:パス名を取得できる(URLにある検索用パラメータ以外の部分を取得)
    • useRouter:ナビゲーションを可能にする(詳細は後で)
  • 検索を実行する大まかな手順は以下
    • 1 ユーザーが入力した情報を取得
      • input要素のonChange属性でevent取得により実現
    • 2 入力された情報でURLを更新
      • useSearchParamsとURLSearchParamsで検索に使われたワードをURLに含めるためのパラメータ文字列を生成
      • usePathnameでパラメータ抜きのURLを取得
      • useRouterで作成されるreplaceメソッドに引数として上で作成したURLとパラメータ文字列を組み合わせた文字列を渡し、URLを更新
    • 3 入力された情報で画面上のテーブルなどの情報を更新
      • クエリー情報をテーブル用のデータ取得コンポーネントにpropで渡して、データ取得してテーブルを再レンダリング
  • キー入力のたびにDBリクエストが飛ばないようにするためにDebouncingが使われる
    • Debouncingは関数が実行される頻度を制限するもの
    • use-debounceのuseDebouncedCallbackを利用すると簡単にDebouncingが実装できる

Chapter12 Mutating Data

  • Server Actionsはサーバーサイドはもちろんクライアントからも呼び出せる直接サーバーサイドで実行される処理のこと
    • APIを分けて作る必要はなく、内包されているようなイメージで良い(公式ページに"Behind the scenes, Server Actions create a POST API endpoint. “とある)
    • よくある実行の形として、JSXのform要素のaction属性に対してServer Actionsとして作成された関数を設定することで、フォーム送信時にServer Actionsを実行できる
  • レコード作成用フォームでServer Actionsを使う場合の記述例
    • 1 Server Actionの型を作成(処理内容はまだ)
      • use server’ディレクティブをファイルの最初の行、もしくは関数の最初の行に設定
      • フォームデータを引数とするasync関数を作成
    • 2 フォームのアクションにServerActionを設定
      • JSXのform要素のaction属性に対してServer Actionsとして作成された関数を設定
    • 3 Server Actionへの処理追加
      • 引数で受け取ったフォームのデータをその後処理しやすいように取得
      • 例:formData.get('status’)
    • 4 型チェック
      • Zodというtypescriptのライブラリを使うと容易にできる
        • z.object()メソッドを使って、型チェックを行えるオブジェクトを作成
          • 作成したオブジェクトのparseメソッドで値を渡し型チェックを行い、問題がなければその戻り値をDBとのやり取りで利用
        • coerceを使うと、型の変換をしてくれる
          • 例:z.coerce.number()
          • 変換できない値が渡された時にはエラーになる
    • 5 DBに対してクエリー実行
      • 型チェックが完了した値を利用してDBに対してクエリを実行
    • 6 キャッシュの削除とリダイレクト
      • DB更新前の情報を元にしたページがキャッシュとして保存されているので古い情報が格納されたキャッシュを削除したい
      • revalidatePath関数を利用することで対象のパスのキャッシュを削除することができる
      • キャッシュ削除後に対象のページにリダイレクトすることで最新の情報を取得するようにサーバーに命令が飛び、最新の情報を表示できる
      • redirect関数を利用することで該当ページにリダイレクトできる
  • パス名にidなどが入る詳細ページを作成したい場合フォルダー名を[]で囲めば作成可能
    • 例:dashboard/invoices/ID番号/editというパスを作りたい場合、dashboard/invoices/[id]とdashboard/invoices/[id]/editフォルダーを作成する
    • パス内の動的な値(例で言うid)は表示するコンポーネントのparamとして取得することが可能
  • Server Actionにidなどの機密性の高い情報を渡す時にはpropではなく、Javascriptのbindメソッドを利用する
    • bindメソッドを利用すると、パラメータがエンコードされた状態でサーバーに渡されることになり安全
    • bindメソッドは引数に特定の値を設定した、新たな関数を生成し戻り値として返す

Chapter13 Handling Errors

  • Next.jsでもエラーハンドリングはtry/catchで対応可能
  • error.tsxファイルを作成することで、予期しないエラーのキャッチの仕方をすべて定義でき、またエラーが発生した際に表示する内容も設定可能
  • 404エラーを発生させるなら、notFoundメソッドが便利
    • 特定の条件に合致した時にはnotFoundメソッドを実行させることで、404エラーが発生したことを知らせることができる
    • 表示する内容はnot-found.tsxファイルで設定可能

Chapter14 Improving Accessibility

  • アクセシビリティとはすべての人間が利用できるようにデザインすることを指す。
    • 目が見えないなどの身体的なハンデを持つ方などを対象
  • Next.jsがデフォルトでインストールするeslint-plugin-jsx-a11yを利用すると、image要素にalt属性が設定されているかなどさまざまなことをチェックしてくれる
  • アクセシビリティを改良するための方法としての例は以下
    • Semantic HTML
      • <div>ではなく、<input>や<option>など、単なる区切り以上の意味を持つタグを利用する
    • Labelling
      • フォームの各要素に要素の説明をするためのラベルを設定する
    • Focus Outline
      • ユーザーが現在、編集対象としている箇所をわかりやすくすること。主にフォーム操作で重要
  • フォームバリデーションには複数の改良ができる
    • Client-sideのバリデーションの例として、フォーム内のinput要素にrequired属性を設定して必須にすることがあげられる
  • サーバーサイドバリデーション
    • 良い点がいくつかある
      • データベースへのクエリ実行前に入力値が正しいフォーマットかチェックできる(クライアント側でも同様)
      • 細工しやすいクライアントサイドのバリデーションを突破しようとするような悪意あるユーザーからの脅威を減らせる
      • どんなデータが正しいのかという情報を持つことができる
    • useFormStateを利用すると、フォームの送信によって実行される関数の結果をStateとして管理可能になる

Chapter15 Adding Authentication

  • AuthenticationとAuthorizationの違い
    • Authentication:その人が誰かを明らかにすること
    • Authorization:その人が誰か分かった上で、特定の操作をする許可を与えること
  • NextAuth.jsを利用するとAuthenticationを容易に搭載できる
    • NextAuthでの認証用の設定ファイルとしてauth.config.tsをプロジェクトのルートフォルダに作成
      • このファイルには以下を設定できる
        • ログイン、ログアウト、エラー、それぞれ用のページへのパス
        • 認証状態を引数として持ち、認証状態によってユーザーの動きを制御するためのWebアプリにアクセスする際に実行される関数
          • どのパスにアクセスした時に実行するかはmiddleware.tsというファイルで設定可能
    • パスワードをDBに保存する時にはハッシュ化したほうが良いが、bcryptを利用すると容易にできる
    • 同一かどうか確認するためにはbcrypt.compareが利用可能

Chapter16 Adding Metadata

  • メタデータとは画面上には表示されないが、検索エンジンやその他のシステムに利用されるWebページに関する情報を指す
    • google検索などの検索結果で上位に表示されたいのなら、特に重要
  • メタデータの中で代表的なのが以下
    • title
    • description
    • keywords
    • favicon(サイトを象徴する、ごく小さいアイコン)
  • メタデータは二つの方法で追加できる
    • Config-based:メタデータ用のオブジェクトもしくは関数を作成する形
    • File-based:メタデータ作成用のファイルで設定する形(例:favicon.icoの作成)

そのほかNext.jsについて知っておいた方が良いこと

Learn Next.jsでNext.jsを学んだ後、Next.jsで個人アプリ開発を進めているいるのですが、その中で学んだことをメモします。

create-next-appで作られるファイルの実行順

create-next-appを利用するとすぐに起動可能なアプリが出来上がります。ただNext.jsアプリを起動してブラウザでアクセスして表示される画面がどのファイルをどんな順番で読み込んで作成しているのかが不明であったため調べました。

調べた結果分かった挙動は以下です。

  1. ルートへのアクセス:
    • ユーザーがアプリケーションのルート (/) にアクセスします。
  2. app/layout.tsx の適用:
    • Next.js はまず layout.tsx ファイルを読み込み、共通のレイアウト(ヘッダー、フッターなど)をレンダリングします。
  3. app/page.tsx の適用
    • layout.tsx 内の {children} に、page.tsx ファイルのコンテンツを渡します。
  4. 最終的なページのレンダリング
    • ユーザーには、layout.tsx のレイアウト内に page.tsx のコンテンツが埋め込まれたページが表示されます。

URLに関係なく表示されるコンポーネント置き場

appフォルダの下はルーティングが関係した情報になるので、URLに関係ないコンポーネントはappフォルダには置かないのが良いです。以下のようにappフォルダの外にcomponentsフォルダを作成して、それをapp/layout.tsxで読み込む形が良いでしょう。

my-next-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   ├── about/
│   │   └── page.tsx
│   ├── styles/
│   │   └── globals.css
│   └── ...
├── components/
│   ├── Sidebar.tsx
│   └── ...
├── public/
├── next.config.js
├── package.json
└── ...

Metadata

以下のような形でどこでも使われていないように見えるMetadataオブジェクトがlayout.tsxには存在します。

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
}

このmetadata オブジェクトは、Next.js 13 の新しいアーキテクチャにおいて、ページのメタ情報を管理するための設定です。Next.js によって自動的にHTMLの <head> セクションに反映されます。

つまり定義しておくだけで勝手にNext.jsが解釈してページの情報として付加してくれます。

どのファイルで定義するかによって適用される範囲が変わるので注意です。

ルートレベルの layout.tsx:app/layout.tsx に設定された Metadata は、アプリケーション全体に適用されます。このメタデータは、すべてのページに共通するデフォルトのメタデータとして機能します。

ページレベルの page.tsx:個々のページ (app/page.tsx など) に設定された Metadata は、そのページが読み込まれるときに適用されます。この場合、ルートレベルのメタデータに加えてページ固有のメタデータが適用されます。

サブルートのレイアウト (app/section/layout.tsx など):特定のセクションやサブルート (app/section/layout.tsx など) に設定された Metadata は、そのセクション内のすべてのページに適用されます。

Reactframework,Next.js

Posted by ラプラス