[初学者向け] Next.js で開発を始める方法

10 min read

想定読者

  • Next.js に触れたことがあまりない人
  • ちょっとした使い方を知りたい人

Next.js とは

Next.js は、Vercel 社が提供する React フレームワークである。

Next.js by Vercel - The React FrameworkProduction grade React applications that scale. The world’s leading companies use Next.js by Vercel to build static and dynamic websites and web applications.https://nextjs.org/

なぜ、Next.js を使うのか

Next.js には以下のフロントエンド開発のベストプラクティスを特徴として持っており、この恩恵を開発の初期段階から享受できる。

  • ゼロコンフィグ
  • ファイルベースルーティング
  • 事前レンダリング
  • 画像やフォントの最適化

セットアップ

Next.js は執筆時点での最新バージョン v12.1.6 を想定。

手動でセットアップも可能だが、体系的に Next.js を学ぶのを目的とするため自動セットアップを利用する。

任意のディレクトリに移動して、下記のコマンドを実行する。コマンドを実行したディレクトリに任意のディレクトリ名(後述の「プロジェクト名」)で Next.js をインストールしたディレクトリが作成される。

npx create-next-app@latest --typescript --use-npm

--use-npmを付けないと yarn でセットアップが行われる。こちらは環境に応じて任意でつける。

上記のコマンドを実行すると以下の流れで Next.js のインストールが行われる。

  1. 下記のように訊かれたら、yを入力
    Need to install the following packages:
      create-next-app@latest
    Ok to proceed? (y)
    
  2. プロジェクト名を訊かれるので、任意のプロジェクト名を入力
    ✔ What is your project named?
    
  3. 作成されたファイル一覧
     .
     ├── .eslintrc.json
     ├── .gitignore
     ├── .next
     ├── README.md
     ├── next-env.d.ts
     ├── next.config.js
     ├── package-lock.json
     ├── package.json
     ├── pages
     │   ├── _app.tsx
     │   ├── about.js
     │   ├── api
     │   │   └── hello.ts
     │   └── index.tsx
     ├── public
     │   ├── favicon.ico
     │   └── vercel.svg
     ├── styles
     │   ├── Home.module.css
     │   └── globals.css
     └── tsconfig.json
    

基本的な開発手順

  1. 下記のコマンドを実行し、開発サーバを起動する
    npm run dev
    
    (他のコマンドについては割愛)
  2. 開発サーバ起動後、http://localhost:3000 でアプリケーションの実行を確認
    (デフォルトの設定だとポートは3000
localhost:3000へアクセスして表示される画面
3. 開発サーバ実行中に任意のファイルを編集するとライブリロードされて内容が反映される

ファイルベースルーティング

pagesディレクトリ内に配置した React コンポーネント(.js,.jsx,.ts,.tsxファイル)によって、ルーティングが決定する。

例えば、以下のような React コンポーネントを pages/about.js というファイルで配置すると、/aboutへとアクセスできるようになる。ディレクトリを任意の名称にして、index を配置する形(pages/about/index.js)でも同様の動きになる。

// pages/about.js

const About = () => {
  return <div>About</div>;
};

export default About;

インデックスルート

indexというファイルは、ルートとしてルーティングされる。

  • pages/index.jsx/
  • pages/about.jsx
    pages/about/index.js/about

ネストされたルート

ネストされたディレクトリ構造も同じようにルーティングされる。

  • pages/posts/first-post.jsx/posts/first-post
  • pages/dashboard/settings/username.jsx/dashboard/settings/username

事前レンダリング(プリレンダリング)とは

Next.js には、SSR(Server-side Rendering)と SG(Static Generation)の 2 つの事前レンダリング形式がある。

事前レンダリングとは、各ページの HTML をクライアントサイドの JavaScript でレンダリングするのではなく、サーバサイドの JavaScript で事前に生成しておくことを指す。

これらの違いは、ページの HTML を生成するタイミングにある。

  • SG(Static Generation): ビルド時に HTML を生成する
  • SSR(Server-side Rendering): リクエストごとに HTML を生成する

事前レンダリングなし

事前レンダリングなし
事前レンダリングなし - 'Pre-rendering - Pre-rendering and Data Fetching | Learn Next.js'より

事前レンダリングがない場合、クライアントサイドで HTML を生成するため、JavaScript によるレンダリングが完了するまでコンテンツを見ることができない。また、JavaScript が無効化された状態では見ることが出来ない。

事前レンダリングあり

事前レンダリング(Next.js利用時)
事前レンダリングあり - 'Pre-rendering - Pre-rendering and Data Fetching | Learn Next.js'より

事前レンダリングの場合、事前に HTML は生成されたものをクライアントサイドはレンダリングする。生成された HTML は JavaScript と関連付けられており、ページが読み込まれた後に JavaScript は実行され、アプリケーションはインタラクティブになる。このプロセスはハイドレーション(Hydration)と呼ばれる。

SG: Static Generation / SSG: Static-site Generation

SG(Static Generation)は、ビルド時に HTML を生成する事前レンダリング方式。

Static Generation
Static Generation - 'Pre-rendering - Pre-rendering and Data Fetching | Learn Next.js'より

We recommend using Static Generation (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
https://nextjs.org/learn/basics/data-fetching/two-forms

ちなみに Next.js は、パフォーマンスの観点から可能な限り SG を使用することを推奨している。

Next.js での利用方法

pages ディレクトリ内のコンポーネントでgetStaticProps()を利用する。

export async function getStaticProps(context) {
  return {
    props: {}, // ページコンポーネントに props として渡す
  };
}

以下はBlogコンポーネントのデータを SG 時に API 経由でセットするケース。

// この関数はサーバーサイドのビルド時(Node.js)に呼び出される
// ブラウザ上ではなく Node.js で実行されるので DOM などへのアクセスはできない
export async function getStaticProps() {
  const res = await fetch("https://.../posts");
  const posts = await res.json();

  // `props: { posts }` を返すことで
  // Blog コンポーネントはビルド時に `posts` を `props` として受け取れる
  return {
    props: {
      posts,
    },
  };
}

// `posts` は、ビルド時に `getStaticProps()` で取得した値が設定される
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  );
}

export default Blog;

いつ使うべきか

  • ページをレンダリングするのに必要なデータが、ビルド時にユーザーのリクエストよりも先に利用可能である場合
  • データをヘッドレス CMS や API から取得する場合
  • データがユーザー固有のものでなく public にキャッシュできる場合
  • SEO などの理由でページを事前レンダリングする必要があり、かつ非常に高速でなければならない場合

SSR: Server-side Rendering

SSR(Server-side Rendering)は、ユーザのリクエストごとに HTML をサーバー側で生成する事前レンダリング方式。

Server-side Rendering
Static Generation - 'Pre-rendering - Pre-rendering and Data Fetching | Learn Next.js'より

Next.js での利用方法

pages ディレクトリ内のコンポーネントでgetServerSideProps を利用する。

export async function getServerSideProps(context) {
  return {
    props: {}, // ページコンポーネントに props として渡す
  };
}

以下はBlogコンポーネントのデータを SSR でセットするケース。

// この関数はサーバーサイドのリクエスト時(Node.js)に呼び出される
// ブラウザ上ではなく Node.js で実行されるので DOM などへのアクセスはできない
export async function getServerSideProps(context) {
  const res = await fetch("https://.../posts");
  const posts = await res.json();

  // `props: { posts }` を返すことで
  // Blog コンポーネントはリクエスト時に `posts` を `props` として受け取れる
  return {
    props: {
      posts,
    },
  };
}

// `posts` は、リクエスト時に `getServerSideProps()` で取得した値が設定される
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  );
}

export default Blog;

いつ使うべきか

  • クエリパラメータで動的にデータが変わるページ
  • HTTP ヘッダーを必要とするページ

参考


WIP

Next Read

[React 18] useEffect が2回実行されてしまう問題の対処法

確認した環境 / 解決方法 / 参考

[Next.js] Emotion SWCを有効にする方法

概要 / 方法 / その他

StorybookでEmotion 11がエラーになる問題の解決方法

状況 / 環境 / 解決方法 / 参考

[Next.js] Qiita と Zenn の 記事一覧(フィード)を取得する方法

やりたいこと / 環境 / フィードの仕様 / 実装