インストールとプロジェクト構造
AliceはMegaShopをローカルで動かしたいと考えていますが, Nuxt 3のディレクトリ規約に戸惑っています。ファイルを間違った場所に置くと, コンポーネントが自動インポートされません。Bobのプロジェクトは設定が乱雑で, ビルドのたびに問題が発生しています。Charlieはチームの開発を標準化するために明確なディレクトリ構造が必要です。
1. 学ぶ内容
- npx nuxi@latest init:プロジェクトの作成とパッケージマネージャーの選択
- コアディレクトリ規約:pages/components/composables/serverなど
- nuxt.config.tsの詳解
- 自動インポートの仕組み
- MegaShopプロジェクト初期化のハンズオンガイド
2. 開発者の実話
(1) ペインポイント:乱雑なディレクトリ構造でコンポーネントが「消える」
AliceはProductCard.vueをsrc/components/shop/に配置しましたが, ページで「Component ProductCard is not found」というエラーが発生しました。Nuxt 3のディレクトリ規約を知らなかったのです。コンポーネントのパスがコンポーネント名を決定します。components/shop/ProductCard.vueは<ShopProductCard />として参照する必要があります。この暗黙のルールは初心者をよくつまずかせます。
(2) Nuxt 3ディレクトリ規約による解決策
Nuxt 3は手動設定の代わりにディレクトリ規約を使用します。正しいディレクトリにファイルを配置すれば自動的に利用可能になり, import文は不要です。規約を理解すれば, Aliceはルールに従ってファイルを整理するだけです:
TEXT
components/
ProductCard.vue → <ProductCard />
shop/
ProductList.vue → <ShopProductList />
(3) 効果:開発効率の倍増
チームがディレクトリ規約を理解すると, Aliceのコンポーネントはもう「消え」なくなり, 新しいメンバーのオンボーディング時間は2日から4時間に短縮されました。
3. Nuxt 3プロジェクトの作成
(1) 初期化コマンド
BASH
# 新しいNuxt 3プロジェクトを作成
npx nuxi@latest init megashop
# または特定のパッケージマネージャーを指定
npx nuxi@latest init megashop --packageManager pnpm
(2) パッケージマネージャーの比較
| 項目 | npm | pnpm | yarn |
|---|---|---|---|
| インストール速度 | 🐢 遅い | ⚡ 最速 | ⚡ 高速 |
| ディスク使用量 | 🔴 多い | 🟢 少ない (ハードリンク) | 🟡 中程度 |
| モノレポ | ⚠️ workspacesが必要 | ✅ ネイティブサポート | ✅ サポートあり |
| 評価 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
(1) ▶ サンプル:初期化と起動
BASH
# ステップ1:プロジェクトを作成
npx nuxi@latest init megashop
# ステップ2:プロジェクトディレクトリに移動
cd megashop
# ステップ3:依存関係をインストール
npm install
# ステップ4:開発サーバーを起動
npm run dev
# → Nuxt dev server running at http://localhost:3000
出力:
TEXT
# コマンド実行成功
(2) ▶ サンプル:package.jsonのコアスクリプト
JSON
{
"name": "megashop",
"private": true,
"scripts": {
"build": "nuxi build",
"dev": "nuxi dev",
"generate": "nuxi generate",
"preview": "nuxi preview",
"postinstall": "nuxi prepare"
},
"dependencies": {
"nuxt": "^3.12.0"
},
"devDependencies": {
"@nuxt/devtools": "latest"
}
}
出力:
JSON
{
"name": "megashop",
"private": true,
"scripts": {
"build": "nuxi build",
"dev": "nuxi dev",
"generate": "nuxi generate",
"preview": "nuxi preview",
"postinstall": "nuxi prepare"
},
"dependencies": {
"nuxt": "^3.12.0"
},
"devDependencies": {
"@nuxt/devtools": "latest"
}
}
4. コアディレクトリ規約
(1) ディレクトリ構造の概要
graph TB
A[megashop/] --> B[pages/ → ルート]
A --> C[components/ → 自動インポートコンポーネント]
A --> D[composables/ → 自動インポート関数]
A --> E[server/ → APIルート]
A --> F[layouts/ → ページレイアウト]
A --> G[plugins/ → 自動登録プラグイン]
A --> H[middleware/ → ルートガード]
A --> I[assets/ → ビルド処理対象]
A --> J[public/ → 静的ファイル]
A --> K[nuxt.config.ts → プロジェクト設定]
A --> L[app.vue → ルートコンポーネント]
(2) 各ディレクトリの役割とルール
| ディレクトリ | 役割 | 自動登録 | MegaShopでの活用 |
|---|---|---|---|
| pages/ | ルートページ | ✅ ルート自動生成 | 商品ページ/カテゴリページ/ホーム |
| components/ | Vueコンポーネント | ✅ 自動インポート | ProductCard/Header/Footer |
| composables/ | コンポーザブル関数 | ✅ 自動インポート | useCart/useProduct |
| server/api/ | APIルート | ✅ 自動登録 | /api/products /api/cart |
| server/middleware/ | サーバーサイドミドルウェア | ✅ グローバル適用 | auth/CORS |
| layouts/ | ページレイアウト | ✅ 自動登録 | default/sidebar |
| plugins/ | プラグイン | ✅ 自動実行 | stripe/payment |
| middleware/ | ルーティングミドルウェア | ✅ 参照可能 | auth/admin |
| assets/ | ビルド処理リソース | ❌ 参照が必要 | CSS/フォント/SCSS |
| public/ | 静的ファイル | ❌ 直接アクセス | favicon/robots.txt |
(1) ▶ サンプル:MegaShopディレクトリ構造
TEXT
megashop/
├── app.vue # ルートコンポーネント
├── nuxt.config.ts # プロジェクト設定
├── pages/
│ ├── index.vue # ホームページ
│ ├── products/
│ │ ├── index.vue # 商品一覧
│ │ └── [id].vue # 商品詳細
│ ├── categories/
│ │ └── [slug].vue # カテゴリページ
│ ├── cart.vue # ショッピングカート
│ └── about.vue # Aboutページ
├── components/
│ ├── AppHeader.vue # → <AppHeader />
│ ├── AppFooter.vue # → <AppFooter />
│ └── product/
│ ├── ProductCard.vue # → <ProductProductCard /> ①
│ └── ProductList.vue # → <ProductProductList /> ①
├── composables/
│ ├── useCart.ts # → 自動インポート
│ └── usePriceFormat.ts # → 自動インポート
├── server/
│ └── api/
│ ├── products/
│ │ └── index.get.ts # GET /api/products
│ └── cart/
│ └── index.post.ts # POST /api/cart
├── layouts/
│ ├── default.vue # デフォルトレイアウト
│ └── sidebar.vue # サイドバーレイアウト
├── middleware/
│ └── auth.ts # 名前付きミドルウェア
├── plugins/
│ └── stripe.client.ts # クライアント専用プラグイン
├── assets/
│ └── css/
│ └── main.css # グローバルスタイル
└── public/
├── favicon.ico
└── robots.txt
出力:
TEXT
実行成功
⚠️ 注意: ①
components/product/ProductCard.vueのデフォルトプレフィックスはProductで, つまり<ProductProductCard />になります。nuxt.config.tsでpathPrefixを設定してプレフィックスを無効にできます。
5. nuxt.config.tsの詳解
(1) コア設定オプション
| オプション | 型 | 説明 | MegaShopの例 |
|---|---|---|---|
| ssr | boolean | グローバルSSR切替 | true |
| modules | array | モジュールリスト | @pinia/nuxt |
| runtimeConfig | object | ランタイム設定 | APIキー/データベースURL |
| app | object | アプリメタデータ | head/title/templateId |
| vite | object | Vite設定 | プロキシ/プラグイン |
| routeRules | object | ルートレベルのレンダリング戦略 | ISR/CSR/キャッシュ |
| components | object | コンポーネントインポート設定 | プレフィックス/スキャンパス |
(1) ▶ サンプル:MegaShop基本設定
TYPESCRIPT
// nuxt.config.ts
export default defineNuxtConfig({
// グローバルSSR設定
ssr: true,
// アプリメタデータ
app: {
head: {
title: 'MegaShop - Premium E-Commerce',
meta: [
{ name: 'description', content: '数百万の商品を世界配送' }
]
}
},
// ランタイム設定 (サーバー専用シークレット)
runtimeConfig: {
// プライベート - サーバーのみ
databaseUrl: process.env.DATABASE_URL,
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
// パブリック - クライアントに公開
public: {
apiBase: process.env.API_BASE || 'http://localhost:3000/api',
stripePublishableKey: process.env.STRIPE_PUBLISHABLE_KEY
}
},
// モジュール
modules: [
'@pinia/nuxt',
'@nuxtjs/tailwindcss'
],
// コンポーネントパスプレフィックス設定
components: [
{ path: '~/components', pathPrefix: false }
]
})
出力:
TEXT
// 実行成功
(2) ▶ サンプル:routeRulesレンダリング戦略
TYPESCRIPT
// nuxt.config.ts - ルートレベルのレンダリングルール
export default defineNuxtConfig({
routeRules: {
// ホームページ:ビルド時に事前レンダリング
'/': { prerender: true },
// 商品一覧:ISR 60秒再検証
'/products': { swr: 60 },
// 商品詳細:ISR 3600秒再検証
'/products/**': { swr: 3600 },
// 管理ダッシュボード:クライアント専用
'/admin/**': { ssr: false },
// API:CORSヘッダー
'/api/**': { cors: true }
}
})
出力:
TEXT
// 実行成功
6. 自動インポートの仕組み
(1) 自動登録プロセス
flowchart LR
A[Nuxtがディレクトリをスキャン] --> B[.nuxt/imports.d.tsを生成]
B --> C[.nuxt/components.d.tsを生成]
C --> D[TypeScript自動補完]
A --> E[.nuxt/routes.tsを生成]
E --> F[Vue Router設定]
(2) 自動インポートの対象範囲
| 種別 | ディレクトリ | プレフィックスルール | 例 |
|---|---|---|---|
| コンポーネント | components/ | ディレクトリパスプレフィックス | ProductCard → <ProductCard /> |
| コンポーザブル | composables/ | useプレフィックス | useCart() → 自動インポート |
| ユーティリティ関数 | utils/ | プレフィックスなし | formatPrice() → 自動インポート |
| 内蔵API | Nuxt 3コア | "use"プレフィックス | useFetch/useState/useRouter |
(1) ▶ サンプル:コンポーザブルの自動インポート
TYPESCRIPT
// composables/usePriceFormat.ts
// インポート不要 - Nuxtが自動インポート
export function usePriceFormat(price: number, currency: string = 'USD'): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency
}).format(price)
}
// 任意のコンポーネントで - 直接使用
// const formatted = usePriceFormat(2999.99) → "$2,999.99"
出力:
TEXT
// 実行成功
(2) ▶ サンプル:コンポーネントの自動インポート検証
VUE
<!-- pages/index.vue -->
<template>
<!-- すべてのコンポーネントが自動インポート, import文不要 -->
<div>
<AppHeader />
<ProductCard :product="featured" />
<AppFooter />
</div>
</template>
<script setup lang="ts">
// すべてのコンポーザブルが自動インポート
const { data: featured } = await useFetch('/api/products/featured')
const price = usePriceFormat(featured.value?.price || 0)
</script>
出力:
TEXT
// 実行成功
7. 総合例:MegaShopプロジェクトの初期化
BASH
# ============================================
# MegaShopプロジェクト初期化
# ゼロから開発サーバー起動までの完全セットアップ
# ============================================
# 1. プロジェクトを作成
npx nuxi@latest init megashop
cd megashop
# 2. コア依存関係をインストール
npm install @pinia/nuxt @nuxtjs/tailwindcss
# 3. ディレクトリ構造を作成
mkdir -p pages/products pages/categories
mkdir -p components/product
mkdir -p composables
mkdir -p server/api/products server/api/cart
mkdir -p layouts
mkdir -p middleware
mkdir -p plugins
mkdir -p assets/css
mkdir -p public
# 4. Gitリポジトリを初期化
git init
git add .
git commit -m "feat: initialize MegaShop with Nuxt 3"
# 5. 開発サーバーを起動
npm run dev
❓ よくある質問
Q
componentsサブディレクトリのコンポーネント名にプレフィックスが付くのはなぜですか?A デフォルトではNuxt 3がディレクトリパスをプレフィックスとして使用するため,
components/product/Card.vueは<ProductCard />になります。nuxt.config.tsでcomponents: [{ path: '~/components', pathPrefix: false }]を設定して無効にできます。Q
runtimeConfigのpublicとprivateの違いは何ですか?A privateフィールドはサーバー側でのみ利用可能 (APIキー/データベースパスワード)で, publicフィールドはクライアントに公開されます。キーを
publicセクションに絶対に保存しないでください。Q
app.vueとpages/は共存できますか?A はい。ただし
app.vueには<NuxtPage />を含めてページをレンダリングする必要があります。pages/ディレクトリがない場合, app.vueが唯一のページになります。Q
assetsとpublicの違いは何ですか?A
assets/のファイルはViteによってビルドされます (参照, 最適化, ハッシュ化が可能)。public/のファイルはそのまま出力ディレクトリにコピーされ, URLで直接アクセスできます。Q .nuxtディレクトリはGitに追加すべきですか?
A いいえ。.nuxtディレクトリはNuxtが自動生成する一時ディレクトリで, .gitignoreに既に含まれています。
nuxi prepareまたはnpm run devを実行すると自動的に再生成されます。Q Nuxt 3はsrcディレクトリ構造をサポートしていますか?
A はい。pages/やcomponents/などのディレクトリをsrc/の下に配置でき, Nuxt 3が自動的に認識します。nuxt.config.tsのdirオプションでカスタマイズも可能です。
📖 まとめ
npx nuxi@latest initでプロジェクトを作成し, パッケージマネージャーにはpnpmが推奨されます- Nuxt 3のコアディレクトリ:pages (ルート), components (コンポーネント), composables (関数), server (API), layouts (レイアウト)
nuxt.config.tsはプロジェクトのコア設定:runtimeConfigがシークレットを管理し,routeRulesがレンダリング戦略を管理します- 自動インポートにより, コンポーネント, コンポーザブル, ユーティリティ関数の手動インポートが不要になります
- MegaShopのディレクトリ構造は規約に従い, すべてのファイルが正しい場所に配置されるようにする必要があります
📝 練習問題
- 基本問題 (難易度:⭐):
nuxi initでプロジェクトを作成し, プロジェクトのディレクトリツリーを描いてください。 - 応用問題 (難易度:⭐⭐):
components/の下に2階層のサブディレクトリを持つコンポーネントを作成し, 自動インポート時の命名規約を検証してください (例:components/shop/product/Card.vueのタグ名は何になるか?)。 - チャレンジ (難易度:⭐⭐⭐):
nuxt.config.tsのrouteRulesを設定し, ホームページを事前レンダリング, 商品ページをISR 60秒, 管理ページをCSRにして, 期待通りに動作することを検証してください。
---|



