このページは、v13.4 の Pages Router と、2023 年 5 月に安定版が出たApp Router の 2 つのプロジェクトの作り方を解説します。

開発の全体の流れ

開発の全体の流れはこのようになります。

  1. GitHubで新しいリポジトリを作成する
  2. ローカルで新しくプロジェクトを作成する。npx create-next-app
  3. 新しく作成したプロジェクトをGitHubのリポジトリにpushする
  4. 開発環境を設定する。例えば、必要なパッケージをnpmやyarnを使ってインストールする、eslintやprettierを設定するなど
  5. 開発を行う。これにはページの作成、API routesの設定、CSSスタイリングなどが含まれる
  6. テストを行う。JestやReact Testing Libraryなどのツールを使ってコンポーネントや関数のテストを書く
  7. Vercelにデプロイする。Vercel CLIを使ってプロジェクトをデプロイ: vercel
  8. カスタムドメインを設定する。Vercelのダッシュボードからカスタムドメインを追加

また、開発中は頻繁にコードをコミットしてGitHubにpushすることをおすすめします。このようにすることで、問題が発生した場合に以前の状態に戻すことが容易になります。また、バージョン管理システムを活用することで、複数の人が同時に作業を行ってもコードの競合を解消することができます。

それでは、どちらかの方法を使ってプロジェクトを作成していきます。

  • App Router を使うパターン(最新の方法。メリットが多いが少し不安定なところもある)
  • Pages Router を使うパターン(旧来の方法。安定している)

GitHub リポジトリをセットアップ

GitHub にログイン後「新しいリポジトリ」を作り、非公開(Private)にします。

App Router でプロジェクトを作成する

次に、ローカルでプロジェクトを作成します。こちらは App Router を使うパターンです。Pages Router から段階的に採用可能です。Pages Router との主な違いとして以下のような点があります。

  • ルートディレクトリは app
  • index.js は page.js
  • _app.tsxlayout.tsx
  • _document.tsxlayout.tsx に統合

それでは、インストールを始めます。

# インストール
npx create-next-app@latest v13.4

インストール時に、次のプロンプトが表示されます。Use App Router のところは Yes を選択します。

✔ Would you like to use TypeScript with this project? … Yes
✔ Would you like to use ESLint with this project? … Yes
✔ Would you like to use Tailwind CSS with this project? … Yes
✔ Would you like to use `src/` directory with this project? … Yes
✔ Use App Router (recommended)? … Yes
✔ Would you like to customize the default import alias? … No

そのままエンターを押していきます。そして、プロジェクトに移動して、開発サーバーを起動します。

cd v13.4

# 起動
npm run dev

http://localhost:3000/ にアクセスし、プロジェクトが正常に動作していることを確認します。

Github に push する

無事に動作していることを確認したら、開発サーバを停止して、Github に push します。 Github でリポジトリを作成し、そのページの「…or create a new repository on the command line」の場所をコピーして、ローカルのプロジェクトに移動し、コマンドに貼り付けます。

VSCode のサイドバーからでも commit できますので、VSCodeからGithubに接続しておきてください。

例(このまま貼り付けないでください)

echo "# リポジトリ名" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/アカウント名/リポジトリ名.git
git push -u origin main

2 回目以降 のアップロードは以下のコマンド。xxxx はコメントを入れてください。

git add .
git commit -m "xxxx"
git push

Next.js v13.4 版ではインストール後、TypeScript と Tailwind CSS が有効になります。

package.js は次のように構成されています。

{
  "name": "v13.4",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@types/node": "20.1.0",
    "@types/react": "18.2.6",
    "@types/react-dom": "18.2.4",
    "autoprefixer": "10.4.14",
    "eslint": "8.40.0",
    "eslint-config-next": "13.4.1",
    "next": "13.4.1",
    "postcss": "8.4.23",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "tailwindcss": "3.3.2",
    "typescript": "5.0.4"
  }
}

作成後のディレクトリはこのようになっています。これは App Router と呼ばれる機能で、従来の Pages Router とは異なるレイアウトシステムを採用しています。

.
├── public
└── src/
    └── app/
        ├── layout.tsx
        └── page.tsx

page.tsx の中身を全部削除し、次のように書き換えます。http://localhost:3000/ にアクセスすると、「HOME です。」と表示されます。

export default function Home() {
  return <h1>HOME です。</h1>
}

次に、要件定義に沿って必要なパッケージをインストールします。

要件定義の例

  • マークダウン対応
  • シンタックスハイライト
  • Emotion
  • TOC
  • Sass
  • 関連記事
  • タグ一覧ページ
  • タグページのページネーション

一括インストール

npmを使用してパッケージを一括でインストールするには、例えば下記のコマンドを実行します。ただし、TypeScriptの型定義ファイルが必要なパッケージについては、それぞれのパッケージに対応する型定義ファイルが提供されているかどうか確認する必要があります。型定義ファイルは通常、パッケージ名に@types/プレフィックスがついた形で提供されています。

npm install @emotion/css @emotion/react @emotion/styled gray-matter react-markdown remark-html remark-prism remark-slug remark-autolink-headings remark-gfm tocbot prismjs prismjs-themes next-sitemap sass remark @types/remark-prism

※ 一部のパッケージ(特に@emotion系のパッケージなど)は、元々TypeScriptで書かれているため、追加で型定義ファイルをインストールする必要はありません。型定義ファイルが提供されていないパッケージの場合、一般的な解決策としては自分で型定義ファイルを作成するか、コミュニティによって作成された型定義ファイルを探すことがあります。

package.json を確認すると、インストールしたパッケージが追加されているのが分かるかと思います。

次に、新しいページを作ります。

例えば about ページを作りたいときは about/page.tsx を作成します。

.
├── public
└── src/
    └── app/
        ├── globals.css
        ├── layout.tsx
        ├── page.tsx
        └── about/
            ├── layout.js
            └── page.tsx

about/page.tsx に以下のように記述します。

export default function Page() {
  return <h1>About です。</h1>
}

layout.js は、ページごとに設定できます。ディレクトリごとに layout.js を作成すると、そのディレクトリ内のすべてのページに適用されます。例えば、about ディレクトリを作り、その中に layout.js を作ると、about ディレクトリ内のすべてのページに適用されます。

meta タグの設定

次に、layout.tsx を開き、title を次のように書き換えてみましょう。開発ツールで head 内を確認するとタイトルが変わっているのが確認できます。

import './globals.css'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'サンプルです',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  )
}

layout.js

次に、Emotion を使ってスタイルを当ててみましょう。layout.js に以下のように記述します。

'use client'

import { Global, css } from '@emotion/react'
import styled from '@emotion/styled'
import '../../styles/reset.min.css'
import '../../styles/globals.css'
import '../../styles/style.scss'
import Image from 'next/image'
import Link from 'next/link'

// metadata をここで定義
const metadata = {
  title: 'タイトル',
  description: 'ここに説明が入ります。',
}

// Emotion styled
const Nav = styled.nav`
  display: flex;
  gap: 80px;
  ul {
    display: flex;
    align-items: center;
    gap: 20px;
  }
`

// ここでグローバルスタイルを定義
const globalStyles = css`
  html {
    font-size: 62.5%;
    height: -webkit-fill-available;
    box-sizing: border-box;
  }
  *,
  *:before,
  *:after {
    box-sizing: inherit;
  }
  * {
    outline: none;
  }
  body {
    font-family: 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', Meiryo, sans-serif;
    font-weight: 400;
    font-size: 1.4rem;
    line-height: 1.5;
    }
`

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ja">
      <body>
        <Global styles={globalStyles} />
        <Nav>
          <Link href="/">
            <Image src="./logo.svg" alt="logo" width={150} height={80} />
          </Link>
          <ul>
            <li>dummy</li>
            <li>dummy</li>
            <li>dummy</li>
            <li>dummy</li>
          </ul>
        </Nav>
        {children}
      </body>
    </html>
  )
}

useRouter

また、useRouter を使っている場合は、next/router から next/navigation に置き換えます。'use client' をファイルの先頭に追加してください。

pages 版

import { useRouter } from 'next/router'

app 版

'use client'
import { useRouter } from 'next/navigation'

getStaticProps

getServerSideProps 及び getStaticProps は使えないので、他の方法で代替する必要があります。

export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

export default function Page({ params }: { params: { slug: string } }) {
  const { slug } = params
  // ...
}

Pages Router でプロジェクトを作成する(今までの方法)

Next.js のプロジェクトを作成します。create-next-app コマンドを使って、TypeScript 対応のプロジェクトを作成します。プロジェクト名はmy-appとします。

# インストール
npx create-next-app@latest my-app

※ こちらは、Pages Router を使うパターンです。YES を選んでいき、Use App Router のところは No を選択します。import alias? のところも、No を選択します。

✔ Would you like to use TypeScript with this project? … Yes
✔ Would you like to use ESLint with this project? … Yes
✔ Would you like to use Tailwind CSS with this project? … Yes
✔ Would you like to use `src/` directory with this project? … Yes
✔ Use App Router (recommended)? … No
✔ Would you like to customize the default import alias? … No

上の選択肢で作成するとディレクトリは次のようになります。

.
├── pages
│   ├── api
│   │   └── hello.ts
│   ├── _app.tsx
│   ├── _document.tsx
│   └── index.tsx
└── styles
    └── globals.css

開発サーバーの起動

作成したプロジェクトディレクトリに移動して、開発サーバーを起動します。 次のコマンドは、必要に応じて、cdコマンドでプロジェクトディレクトリに移動し、npm run dev を実行してください。すると、開発サーバーが起動します。サーバーを停止するときは Ctrl + C を押します。

cd my-app

# 起動
npm run dev

# 停止する場合
ctrl + c

# プロジェクト ビルド
npm run build

# ビルドした生成物を元にサーバーを立ち上げる場合
npm run start

# info
next info

ブラウザで http://localhost:3000 にアクセスし、プロジェクトが正常に動作していることを確認します。

ページを追加するときは Pages Router にファイルを追加します。index.tsx をコピーして about.tsx を追加すると、http://localhost:3000/aboutでアクセスできます。

public ディレクトリの作成

画像、フォントなどの静的アセットを格納するフォルダーを作ります。ディレクトリ public 内のファイルは、/ から参照できます。例えば、public/image.pngは、<img src="/image.png" />として参照できます。

.
├── .git
├── public
├── components
└── src/
    ├── pages/
    │   └── index.tsx
    └── styles/
        └── globals.css

styles ディレクトリの作成

CSS を格納するフォルダーを作ります。

components ディレクトリの作成

コンポーネントを格納するフォルダーを作ります。

プロジェクトを削除するには

何度でもプロジェクトを作って、色々試したくなると思います。 プロジェクトごと削除するには、以下の手順を実行してください。

ターミナル(コマンドプロンプト)を開き、削除するプロジェクトのディレクトリ(フォルダ)に移動します。cd コマンドを使用して、削除したいプロジェクトのディレクトリに移動します。例えば、プロジェクトが my-app という名前の場合:

cd my-app

次に、ターミナル(コマンドプロンプト)で、一つ上のディレクトリに戻ります。以下のコマンドを使用してください。

cd ..

プロジェクトを削除するには、以下のコマンドを実行します。このコマンドは、ディレクトリとその中にあるすべてのファイルを削除します。注意: この操作は取り消せません。データが失われる可能性があるため、注意して実行してください。

Mac または Linux の場合:

rm -rf my-app

Windows の場合:

rmdir /s /q my-app

これで、プロジェクトが完全に削除されます。プロジェクトを削除する前に、必要なデータやファイルをバックアップしておくことをお勧めします。Github のリポジトリを削除するには、[危険なゾーン] の [このリポジトリを削除] をクリックします。

次のページからは、pages 版ですすめていきます。