【Next】入門者必見!TypeScriptでNextアプリの環境構築と構造を理解する

Next,React

kamiです。
TwitterYoutubeもやってます。

今回は入門者必見!TypeScriptでNextアプリの環境構築と構造を理解するの紹介です。

Nextとは?

Next.jsとは、Reactをベースに開発されたフロントエンドフレームワークになります。

Reactとの違い

Next

  1. レンダリング方式
    • サーバーサイドレンダリング(SSR)がデフォルト
    • スタティックサイト生成(SSG)もサポート
    • クライアントサイドも"use client"で使用可能
  2. ルーティング
    • ファイルシステムベースのルーティング
    • app/やpages/ディレクトリ構造でルーティング自動生成
    • 動的ルーティングも簡単に実装可能
  3. 環境構築
    • 開発に必要な機能が最初から組み込み
    • 最小限の設定で開発開始可能
  4. データフェッチ
    • サーバーコンポーネントでのデータフェッチ
    • 自動的なキャッシュと再検証機能
    • サーバーアクションでのフォーム処理
  5. パフォーマンス最適化
    • 画像最適化機能が組み込み済み
    • 自動コード分割
    • フォント最適化
    • ビルド時の自動最適化

React

  1. レンダリング方式
    • クライアントサイドレンダリング(CSR)がデフォルト
    • JavaScriptを使って、ブラウザ上でUIをレンダリング
  2. ルーティング
    • デフォルトではルーティング機能なし
    • React RouterなどのライブラリBを別途導入が必要
  3. 環境構築
    • プロジェクト開始時に多くの設定が必要
    • Webpack設定やその他機能を手動で設定
  4. データフェッチ
    • useEffectやカスタムフックを使って実装
    • 状態管理は別途ReduxやRecoilなどが必要
  5. パフォーマンス最適化
    • 画像最適化、コード分割は手動実装が必要
    • パフォーマンスチューニングは開発者次第

スポンサードサーチ

NextをAppを作成

ターミナルで次のコマンドをコピー&ペーストしてください。
「next-ts-app」はアプリ名になり「–typescript」はオプションでTypeScriptを指定しています。

npx create-next-app@latest next-ts-app --typescript

Ok to proceed? (y) 

Ok to proceed? (y) 
  1. プロジェクトの作成を続行してよいかの確認を行います。
  2. インストールされる依存関係(パッケージ)の確認します。

y または Enter: インストールを続行して、nでインストールをキャンセルします。

このときインストールされる主な依存関係は次になります(一例)

next
react
react-dom
typescript
@types/react
@types/node

Would you like to use ESLint?

Would you like to use ESLint

ESLint はJavaScript/TypeScriptのコード品質とスタイルをチェックするツールです。
Yes を選択することを推奨します。

ESLintの利点

  • コードの一貫性を保つ
  • バグの早期発見
  • タイプミスの防止
  • ベストプラクティスの強制
  • チーム開発での品質維持

Would you like to use Tailwind CSS?

Would you like to use Tailwind CSS?

Tailwind CSSは、ユーティリティファーストのCSSフレームワークです。

YesにするとTailwind CSSがインストールされ、パッケージや設定ファイルが追加されます。
Noの場合は通常のCSSスタイリングのみが使用できます。

Would you like your code inside a src/ directory?

Would you like your code inside a `src/` directory?

プロジェクトに「src」ディレクトリを配置するかどうかの選択です。

Yesの場合

next-ts-app/
├── src/             # ソースコードはここに
│   ├── app/
│   ├── components/
│   ├── styles/
│   └── lib/
├── public/          # 静的ファイル
├── package.json
└── ...その他設定ファイル

srcディレクトリを使用するメリット

  1. コードの整理
    • ソースコードとビルド設定を明確に分離
    • プロジェクトルートがすっきりする
  2. 一般的な慣習
    • 多くのReactプロジェクトで採用
    • チーム開発で分かりやすい

Noの場合

next-ts-app/
├── app/
├── components/
├── styles/
├── lib/
├── public/
├── package.json
└── ...その他設定ファイル

srcディレクトリを使用するデメリット

  • ルートディレクトリが混雑:
    • ソースコードと設定ファイルが同じ階層に
    • プロジェクトが大きくなると管理が難しい
  • 非標準的
    • モダンなReactプロジェクトではsrc/が一般的
    • 他の開発者が混乱する可能性

Would you like to use App Router? (recommended)

Would you like to use App Router? (recommended)

App Router導入についてです。

App RouterはNext.js 13以降で導入された新しいルーティングシステムです。
端的に伝えると「フォルダとファイルでURLが決まる新しいルーティングシステム」です。

appフォルダ内のファイル構成がそのままURLに反映されます。

App Routeあり

src/
└── app/
    ├── page.tsx         # トップページ (/)
    ├── about/           # アバウトページ (/about)
    │   └── page.tsx     
    ├── blog/            # ブログ一覧 (/blog)
    │   ├── page.tsx     
    │   └── [id]/        # 個別記事 (/blog/1, /blog/2...)
    │       └── page.tsx  
    └── layout.tsx       # 全ページ共通のレイアウト

App Router初学者には複雑なのでディレクトリ、ファイルの使わかたを覚えておきましょう

icon

App Routerを使う場合は次のようになっています

  • pagesではなくappディレクトリを使用
  • index.tsx → page.tsxを使用
  • _app.tsx → layout.tsxを使用
  • ファイル構造がそのままルーティングに(about.tsx → about/page.tsx)
  • サーバーコンポーネントがデフォルト
  • レイアウト、ローディング、エラーの扱いが直感的(layout.tsx, loading.tsx, error.tsx)
  • データフェッチがより簡単に(.tsxファイル内で直接非同期処理が可能)
  • より高速なパフォーマンス(サーバーサイドレンダリングの強化)

各ディレクトリやファイルの説明例になります。

  • src/ :プロジェクトのソースコードを格納するルートディレクトリ
  • app/ :Next.jsのApp Routerのルートディレクトリ
  • page.tsx :トップページのコンテンツを表示するファイル (URLは /)
  • about/ :アバウトページのディレクトリ (URLは /about)
  • about/page.tsx :アバウトページのコンテンツを表示するファイル
  • blog/ :ブログ関連ページのディレクトリ (URLは /blog)
  • blog/page.tsx :ブログ一覧ページのコンテンツを表示するファイル
  • blog/[id]/ :動的なブログ記事ページのディレクトリ ([id]は可変の値)
  • blog/[id]/page.tsx :個別のブログ記事ページを表示するファイル (URLは /blog/1 など)
  • layout.tsx :全ページで共通して使用されるレイアウトファイル(ヘッダー、フッターなど)

App Routeなし

src/
└── pages/
    ├── index.tsx         # トップページ (/)
    ├── about.tsx         # アバウトページ (/about)
    ├── blog/
    │   ├── index.tsx     # ブログ一覧ページ (/blog)
    │   └── [id].tsx      # 個別ブログ記事ページ (/blog/1 など)
    └── _app.tsx          # 全ページで共通して使用されるレイアウトファイル
icon

App Routerを使わない場合は次のようになっています

  • appがなくpagesディレクトリを使用
  • page.tsx → index.tsx を使用
  • layout.tsx → _app.tsx を使用
  • ファイル名がそのままルーティングに(about/page.tsx → about.tsx)

Would you like to use Turbopack for next dev?

Would you like to use Turbopack for next dev?

Turbopackは、Next.jsの開発環境をより高速にするために作られた新しいバンドラーです。Webpackの後継として開発されており、Rustで書かれているため処理が非常に高速です。

ただし、現時点(2024年11月)ではベータ版であり機能が限定的で安定性に欠けるため、本番プロジェクトでの使用は推奨されません。
そのため、特に実験目的でない限り「No」を選択することをお勧めします。

Would you like to customize the import alias (@/* by default)?

Would you like to customize the import alias (@/* by default)?

インポートエイリアス(@/*)は、ファイルパスを簡潔に書くための機能です。「Yes」を推奨します。

エイリアスを使うと、相対パスで遡る必要がなく、コードが読みやすくなり保守性が高まります。
特に深い階層のファイルを参照する際に便利なため、「Yes」を選択することをお勧めします。

もし、パスについての概念の知識が浅く、理解を深めたいのであればNoでもいいと思います。

エイリアスあり

// エイリアスあり (Yes) - @がsrcディレクトリを指す
import { Button } from "@/components/Button"
import { getData } from "@/lib/getData"

エイリアスなし

// エイリアスなし (No)
import { Button } from "../../../components/Button"
import { getData } from "../../../../lib/getData"

Nextアプリのプロジェクト構造

├── public/                 # 静的ファイルを格納するディレクトリ
│   ├── file.svg
│   ├── globe.svg
│   ├── next.svg
│   ├── vercel.svg
│   └── window.svg
├── src/                    # ソースコードのメインディレクトリ
│   └── app/                # App Routerのルートディレクトリ
│       ├── favicon.ico     # ファビコン
│       ├── fonts/          # フォントファイル
│       ├── globals.css     # グローバルCSS
│       ├── layout.tsx      # 共通レイアウト
│       └── page.tsx        # トップページ
├── package.json            # プロジェクトの依存関係と設定
├── postcss.config.mjs      # PostCSSの設定ファイル
├── tailwind.config.ts      # Tailwindの設定ファイル
└── tsconfig.json           # TypeScriptの設定ファイル

public

静的ファイルを格納するディレクトリ

src

ソースコードのメインディレクトリ

package.json

プロジェクトの依存関係と設定

tsconfig.json

TypeScriptの設定ファイル

一番最初に呼ばれるファイル

src/app/layout.tsx

「src/app/layout.tsx」が一番最初に呼ばれるファイルです。
コメント入れて分かりやすくしています。

// フォントとメタデータの設定
import type { Metadata } from "next";  // メタデータの型定義をインポート
import localFont from "next/font/local";  // ローカルフォントを使用するための機能
import "./globals.css";  // グローバルCSSの読み込み

// カスタムフォントの設定
const geistSans = localFont({
  src: "./fonts/GeistVF.woff",  // サンセリフフォント
  variable: "--font-geist-sans",  // CSSカスタムプロパティ名
  weight: "100 900",  // フォントウェイトの範囲
});

const geistMono = localFont({
  src: "./fonts/GeistMonoVF.woff",  // 等幅フォント
  variable: "--font-geist-mono",
  weight: "100 900",
});

// サイトのメタデータ設定
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

// ルートレイアウト
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
        // フォント変数とアンチエイリアスを適用
      >
        {children} {/* ここにpage.tsxの内容が自動的に挿入される */}
      </body>
    </html>
  );
}
icon

{children}でpage.tsxを読み込んでいます。
レンダリングすると次のようになります。

<!-- 実際のレンダリング結果 -->
<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="utf-8">
   <title>Create Next App</title>
   <meta name="description" content="Generated by create next app">
   <!-- Next.jsが自動的に追加するその他のメタタグやスタイル -->
 </head>
 <body class="__variable_20f6c2 __variable_daf498 antialiased">
   <!-- geistSans.variable = __variable_20f6c2 -->
   <!-- geistMono.variable = __variable_daf498 -->

   <!-- ここにpage.tsxの内容が挿入される -->
   <main>
     <h1>Welcome to Next.js!</h1>
     <!-- page.tsxのその他のコンテンツ -->
   </main>

   <!-- Next.jsが自動的に追加するスクリプト -->
 </body>
</html>
  • __variable_xxxxx クラスは、フォント変数のためにNext.jsが自動生成したユニークなクラス名
  • antialiased クラスでフォントのアンチエイリアシングが適用
  • ページコンテンツ(page.tsx)はタグ内に自動的に挿入される
  • 必要なメタタグやスクリプトはNext.jsが自動的に追加

スポンサードサーチ

サンプルでHeaderやFooterを追加

先ほど学んだ、「一番最初に呼ばれるファイル」を参考に、
HeaderやFooterを追加した場合のtreeやlayout.tsxを見てみましょう

HeaderやFooterを追加した場合のディレクトリ構成

appディレクトリにコンポーネントディレクトリを作って、そこにHeaderやFooter用のファイルを作成します。

src/
└── app/
   ├── components/           #共通コンポーネント用ディレクトリ(新規作成)
   │   ├── Header.tsx        #ヘッダーコンポーネント(新規作成)
   │   └── Footer.tsx        #フッターコンポーネント(新規作成)
   ├── fonts/                #既存のフォントディレクトリ
   │   ├── GeistVF.woff      #既存
   │   └── GeistMonoVF.woff  #既存
   ├── favicon.ico           #既存
   ├── globals.css           #既存
   ├── layout.tsx            #既存(Headerとfooterを追加)
   └── page.tsx              #既存

HeaderやFooterを追加した場合のlayout.tsx

作成したHeaderコンポーネントやFooterコンポーネントをlayout内で呼び出すことで、ファイルが読み込まれます。

import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import Header from "./components/Header";
import Footer from "./components/Footer";

const geistSans = localFont({
  src: "./fonts/GeistVF.woff",
  variable: "--font-geist-sans",
  weight: "100 900",
});

const geistMono = localFont({
  src: "./fonts/GeistMonoVF.woff",
  variable: "--font-geist-mono",
  weight: "100 900",
});

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

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <Header />
        <main className="min-h-screen">
          {children}
        </main>
        <Footer />
      </body>
    </html>
  );
}

HeaderやFooterを追加した場合のレンダリング結果

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Create Next App</title>
    <meta name="description" content="Generated by create next app">
  </head>
  <body class="__variable_20f6c2 __variable_daf498 antialiased">
    <!-- Header -->
    <header>
      <nav>
        <!-- ヘッダーの内容 -->
      </nav>
    </header>

    <!-- Main content -->
    <main class="min-h-screen">
      <!-- page.tsxの内容 -->
    </main>

    <!-- Footer -->
    <footer>
      <!-- フッターの内容 -->
    </footer>
  </body>
</html>

Next,ReactNext

Posted by kami