Next.js完全ガイド初心者向け。今すぐ試せるコード付き


## 1. Next.jsとは

Next.jsは、Reactベースのフレームワークで、高速で効率的なウェブアプリケーション開発を可能にします。

```jsx
// Next.jsの基本的な構造
my-app/
  ├── pages/
  │   └── index.js
  ├── public/
  ├── styles/
  └── package.json
```

この構造が、Next.jsプロジェクトの基本となります。

## 2. Next.jsの特徴

Next.jsには以下のような特徴があります：

- サーバーサイドレンダリング（SSR）
- 静的サイト生成（SSG）
- ファイルベースのルーティング
- APIルート

```jsx
// pages/index.js (SSRの例)
export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/data')
  const data = await res.json()
  return { props: { data } }
}

export default function Home({ data }) {
  return <div>{data.title}</div>
}
```

このコードは、サーバーサイドでデータをフェッチし、それをページコンポーネントに渡す例です。

## 3. 開発環境のセットアップ

Next.jsプロジェクトを始めるには、以下のコマンドを実行します：

```bash
npx create-next-app@latest my-blog
cd my-blog
npm run dev
```

これにより、新しいNext.jsプロジェクトが作成され、開発サーバーが起動します。

## 4. ページの作成

Next.jsでは、`pages`ディレクトリ内のファイルが自動的にルートになります。

```jsx
// pages/index.js
export default function Home() {
  return <h1>ようこそ、Next.jsブログへ！</h1>
}
```

このコードで、トップページが作成されます。

## 5. ルーティング

Next.jsは、ファイルベースのルーティングを採用しています。

```jsx
// pages/posts/[id].js
import { useRouter } from 'next/router'

export default function Post() {
  const router = useRouter()
  const { id } = router.query

  return <p>ポストID: {id}</p>
}
```

この例では、動的ルーティングを使用して、URLパラメータを取得しています。

## 6. レイアウトの作成

共通のレイアウトを作成することで、コードの再利用性が高まります。

```jsx
// components/Layout.js
export default function Layout({ children }) {
  return (
    <div>
      <header>ヘッダー</header>
      <main>{children}</main>
      <footer>フッター</footer>
    </div>
  )
}

// pages/_app.js
import Layout from '../components/Layout'

function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  )
}

export default MyApp
```

この設定により、全てのページに共通のレイアウトが適用されます。

## 7. スタイリング

Next.jsは、CSSモジュールをサポートしています。

```jsx
// styles/Home.module.css
.title {
  color: blue;
  font-size: 24px;
}

// pages/index.js
import styles from '../styles/Home.module.css'

export default function Home() {
  return <h1 className={styles.title}>スタイリングの例</h1>
}
```

このように、コンポーネント固有のスタイルを簡単に適用できます。

## 8. 画像の最適化

Next.jsの`Image`コンポーネントを使用すると、自動的に画像が最適化されます。

```jsx
import Image from 'next/image'

export default function Avatar() {
  return <Image src="/avatar.png" alt="アバター" width={50} height={50} />
}
```

このコードは、画像の遅延読み込みや適切なサイズ変更を自動的に行います。

## 9. APIルート

Next.jsでは、サーバーレスAPIを簡単に作成できます。

```javascript
// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'こんにちは！' })
}
```

このAPIは`/api/hello`でアクセス可能になります。

## 10. データフェッチング

Next.jsには、データフェッチングのための特別な関数があります。

```jsx
// pages/index.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
  }
}

export default function Home({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
```

この例では、ビルド時にデータをフェッチし、ページコンポーネントにpropsとして渡しています。

## 11. 動的ルーティング

動的ルーティングを使用すると、パラメータに基づいてページを生成できます。

```jsx
// pages/posts/[id].js
export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }))

  return { paths, fallback: false }
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`)
  const post = await res.json()

  return { props: { post } }
}

export default function Post({ post }) {
  return <h1>{post.title}</h1>
}
```

この例では、全ての可能なパスを生成し、各パスに対応するデータをフェッチしています。

## 12. SEO対策

Next.jsでは、`next/head`を使用してメタタグを簡単に設定できます。

```jsx
import Head from 'next/head'

export default function Page() {
  return (
    <>
      <Head>
        <title>ページタイトル</title>
        <meta name="description" content="ページの説明" />
      </Head>
      <h1>ページコンテンツ</h1>
    </>
  )
}
```

これにより、各ページに適切なメタ情報を設定し、SEO対策を行うことができます。

## 13. パフォーマンス最適化

Next.jsには、パフォーマンス最適化のための機能が多数あります。

```jsx
import dynamic from 'next/dynamic'

const DynamicComponent = dynamic(() => import('../components/heavy-component'))

export default function Home() {
  return (
    <div>
      <h1>ホーム</h1>
      <DynamicComponent />
    </div>
  )
}
```

この例では、動的インポートを使用して、必要な時にのみコンポーネントを読み込んでいます。

## 14. 認証の実装

Next.jsでの認証実装は、通常、APIルートとクライアントサイドの状態管理を組み合わせて行います。

```jsx
// pages/api/login.js
import { sign } from 'jsonwebtoken'

export default function handler(req, res) {
  const { username, password } = req.body

  if (username === 'admin' && password === 'password') {
    const token = sign({ username }, process.env.JWT_SECRET)
    res.status(200).json({ token })
  } else {
    res.status(401).json({ message: '認証失敗' })
  }
}

// pages/login.js
import { useState } from 'react'
import { useRouter } from 'next/router'

export default function Login() {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const router = useRouter()

  const handleSubmit = async (e) => {
    e.preventDefault()
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
    })
    if (res.ok) {
      const { token } = await res.json()
      localStorage.setItem('token', token)
      router.push('/dashboard')
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="submit">ログイン</button>
    </form>
  )
}
```

この例では、簡単なログイン機能を実装しています。実際のアプリケーションでは、より堅牢な認証システムが必要です。

## 15. テスト

Next.jsアプリケーションのテストには、Jest和Reactテスティングライブラリを使用できます。

```jsx
// __tests__/index.test.js
import { render, screen } from '@testing-library/react'
import Home from '../pages/index'

describe('Home', () => {
  it('renders a heading', () => {
    render(<Home />)

    const heading = screen.getByRole('heading', {
      name: /welcome to next\.js!/i,
    })

    expect(heading).toBeInTheDocument()
  })
})
```

このテストは、ホームページに特定の見出しが表示されることを確認します。

## 16. デプロイ

Next.jsアプリケーションは、Vercelに簡単にデプロイできます。

```bash
npm install -g vercel
vercel
```

これらのコマンドを実行すると、アプリケーションがVercelにデプロイされます。

## 17. 国際化対応

Next.jsは、組み込みの国際化サポートを提供しています。

```jsx
// next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'ja'],
    defaultLocale: 'en',
  },
}

// pages/index.js
import { useRouter } from 'next/router'

export default function Home() {
  const { locale } = useRouter()
  return <h1>{locale === 'en' ? 'Welcome' : 'ようこそ'}</h1>
}
```

この設定により、`/`と`/ja`の両方のルートが生成されます。

## 18. PWA対応

Next.jsアプリケーションをPWA（Progressive Web App）にするには、`next-pwa`パッケージを使用します。

```javascript
// next.config.js
const withPWA = require('next-pwa')

module.exports = withPWA({
  pwa: {
    dest: 'public',
  },
})
```

この設定により、アプリケーションがオフラインでも動作するようになります。

## 19. TypeScriptの導入

Next.jsはTypeScriptを標準でサポートしています。

```typescript
// pages/index.tsx
import { GetStaticProps, NextPage } from 'next'

interface Props {
  title: string
}

const Home: NextPage<Props> = ({ title }) => {
  return <h1>{title}</h1>
}

export const getStaticProps: GetStaticProps = async () => {
  return { props: { title: 'Welcome to Next.js!' } }
}

export default Home
```

このコードは、TypeScriptを使用してページコンポーネントとデータフェッチング関数を定義しています。

## 20. 実践的なブログ作成例

最後に、これまでの知識を活用して、簡単なブログアプリケーションを作成してみましょう。

```jsx
// pages/index.js
import Link from 'next/link'

export default function Home({ posts }) {
  return (
    <div>
      <h1>ブログ記事一覧</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <Link href={`/posts/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  const posts = await res.json()

  return {
    props: {
      posts: posts.slice(0, 5),
    },
  }
}

// pages/posts/[id].js
import { useRouter } from 'next/router'

export default function Post({ post }) {
  const router = useRouter()

  if (router.isFallback) {
    return <div>Loading...</div>
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  )
}

export async function getStaticPaths() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts')
  const posts = await res.json()

  const paths = posts.slice(0, 5).map((post) => ({
    params: { id: post.id.toString() },
  }))

  return { paths, fallback: true }
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`)
  const post = await res.json()

  return { props: { post } }
}
```

この例では、外部APIからブログ記事のデータを取得し、トップページに表示しています。各記事にはリンクが設定されており、クリックすると詳細ページに遷移します。詳細ページでは、記事の全文を表示しています。

以上が、Next.jsを使用した実践的なブログアプリケーションの基本的な実装例です。この基礎をもとに、さら