Nuxt: 安装与项目结构

最后更新:2026-08-26

Alice 想在本机跑起 MegaShop,却被 Nuxt 3 的目录约定搞晕——文件放错位置组件就不自动导入。Bob 管理的项目配置混乱,每次构建都出问题。Charlie 需要一个清晰的目录规范来统一团队开发。

1. 你将学到


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
# Create new Nuxt 3 project
npx nuxi@latest init megashop

# Or with specific package manager
npx nuxi@latest init megashop --packageManager pnpm

(2) 包管理器对比

维度 npm pnpm yarn
安装速度 🐢 慢 ⚡ 最快 ⚡ 快
磁盘占用 🔴 高 🟢 低(硬链接) 🟡 中
Monorepo ⚠️ 需 workspaces ✅ 原生支持 ✅ 支持
推荐度 ⭐⭐ ⭐⭐⭐ ⭐⭐⭐

▶ 示例:初始化与启动

BASH
# Step 1: Create project
npx nuxi@latest init megashop

# Step 2: Enter project directory
cd megashop

# Step 3: Install dependencies
npm install

# Step 4: Start dev server
npm run dev
# → Nuxt dev server running at http://localhost:3000

输出:

TEXT 📖 仅展示
# 命令执行成功

▶ 示例: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) 目录结构全景

100%
graph TB
    A[megashop/] --> B[pages/ → Routes]
    A --> C[components/ → Auto-import Components]
    A --> D[composables/ → Auto-import Functions]
    A --> E[server/ → API Routes]
    A --> F[layouts/ → Page Layouts]
    A --> G[plugins/ → Auto-register Plugins]
    A --> H[middleware/ → Route Guards]
    A --> I[assets/ → Processed by Build]
    A --> J[public/ → Static Files]
    A --> K[nuxt.config.ts → Project Config]
    A --> L[app.vue → Root Component]

(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

▶ 示例:MegaShop 目录规划

TEXT 📖 仅展示
megashop/
├── app.vue                    # Root component
├── nuxt.config.ts             # Project config
├── pages/
│   ├── index.vue              # Homepage
│   ├── products/
│   │   ├── index.vue          # Product list
│   │   └── [id].vue           # Product detail
│   ├── categories/
│   │   └── [slug].vue         # Category page
│   ├── cart.vue               # Shopping cart
│   └── about.vue              # About page
├── components/
│   ├── AppHeader.vue          # → <AppHeader />
│   ├── AppFooter.vue          # → <AppFooter />
│   └── product/
│       ├── ProductCard.vue    # → <ProductProductCard /> ①
│       └── ProductList.vue    # → <ProductProductList /> ①
├── composables/
│   ├── useCart.ts             # → auto-imported
│   └── usePriceFormat.ts      # → auto-imported
├── server/
│   └── api/
│       ├── products/
│       │   └── index.get.ts   # GET /api/products
│       └── cart/
│           └── index.post.ts  # POST /api/cart
├── layouts/
│   ├── default.vue            # Default layout
│   └── sidebar.vue            # Sidebar layout
├── middleware/
│   └── auth.ts                # Named middleware
├── plugins/
│   └── stripe.client.ts       # Client-only plugin
├── assets/
│   └── css/
│       └── main.css           # Global styles
└── 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 组件导入配置 前缀/扫描路径

▶ 示例:MegaShop 基础配置

TYPESCRIPT
// nuxt.config.ts
export default defineNuxtConfig({
  // Global SSR setting
  ssr: true,

  // App metadata
  app: {
    head: {
      title: 'MegaShop - Premium E-Commerce',
      meta: [
        { name: 'description', content: 'Millions of products, shipped worldwide' }
      ]
    }
  },

  // Runtime config (server-only secrets)
  runtimeConfig: {
    // Private - server only
    databaseUrl: process.env.DATABASE_URL,
    stripeSecretKey: process.env.STRIPE_SECRET_KEY,
    // Public - exposed to client
    public: {
      apiBase: process.env.API_BASE || 'http://localhost:3000/api',
      stripePublishableKey: process.env.STRIPE_PUBLISHABLE_KEY
    }
  },

  // Modules
  modules: [
    '@pinia/nuxt',
    '@nuxtjs/tailwindcss'
  ],

  // Component path prefix setting
  components: [
    { path: '~/components', pathPrefix: false }
  ]
})

输出:

TEXT 📖 仅展示
// 执行成功

▶ 示例:routeRules 渲染策略

TYPESCRIPT
// nuxt.config.ts - route-level rendering rules
export default defineNuxtConfig({
  routeRules: {
    // Homepage: pre-render at build time
    '/': { prerender: true },
    // Product list: ISR with 60s revalidation
    '/products': { swr: 60 },
    // Product detail: ISR with 3600s revalidation
    '/products/**': { swr: 3600 },
    // Admin dashboard: client-side only
    '/admin/**': { ssr: false },
    // API: CORS headers
    '/api/**': { cors: true }
  }
})

输出:

TEXT 📖 仅展示
// 执行成功

6. Auto-imports 机制原理

(1) 自动注册流程

100%
flowchart LR
    A[Nuxt Scan Directories] --> B[Generate .nuxt/imports.d.ts]
    B --> C[Generate .nuxt/components.d.ts]
    C --> D[TypeScript Auto-complete]
    A --> E[Generate .nuxt/routes.ts]
    E --> F[Vue Router Config]

(2) 自动导入范围

类型 目录 前缀规则 示例
组件 components/ 目录路径前缀 ProductCard → <ProductCard />
Composable composables/ use 前缀 useCart() → auto-imported
工具函数 utils/ 无前缀 formatPrice() → auto-imported
内置 API Nuxt 3 内核 use 前缀 useFetch/useState/useRouter

▶ 示例:Composable 自动导入

TYPESCRIPT
// composables/usePriceFormat.ts
// No need to import - auto-imported by Nuxt
export function usePriceFormat(price: number, currency: string = 'USD'): string {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency
  }).format(price)
}

// In any component - use directly
// const formatted = usePriceFormat(2999.99) → "$2,999.99"

输出:

TEXT 📖 仅展示
// 执行成功

▶ 示例:组件自动导入验证

VUE
<!-- pages/index.vue -->
<template>
  <!-- All components auto-imported, no import statement needed -->
  <div>
    <AppHeader />
    <ProductCard :product="featured" />
    <AppFooter />
  </div>
</template>

<script setup lang="ts">
// All composables auto-imported
const { data: featured } = await useFetch('/api/products/featured')
const price = usePriceFormat(featured.value?.price || 0)
</script>

输出:

TEXT 📖 仅展示
// 执行成功

7. 综合示例:MegaShop 项目初始化

BASH
# ============================================
# MegaShop Project Initialization
# Complete setup from zero to running dev server
# ============================================

# 1. Create project
npx nuxi@latest init megashop
cd megashop

# 2. Install core dependencies
npm install @pinia/nuxt @nuxtjs/tailwindcss

# 3. Create directory structure
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. Initialize Git repository
git init
git add .
git commit -m "feat: initialize MegaShop with Nuxt 3"

# 5. Start development server
npm run dev

❓ 常见问题

Q components 子目录的组件名为什么有前缀?
A Nuxt 3 默认用目录路径作前缀,components/product/Card.vue 变成 <ProductCard />。可在 nuxt.config.ts 设 components: [{ path: '~/components', pathPrefix: false }] 关闭。
Q runtimeConfig 的 public 和私有字段有什么区别?
A 私有字段仅在服务端可用(API Key/数据库密码),public 字段会暴露到客户端。永远不要把密钥放在 public 里。
Q app.vue 和 pages/ 可以共存吗?
A 可以,但 app.vue 必须包含 <NuxtPage /> 来渲染页面。如果没有 pages/ 目录,app.vue 就是唯一的页面。
Q assets 和 public 有什么区别?
A assets/ 里的文件会经过 Vite 构建(可引用、可优化、可 hash),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 选项自定义。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 nuxi init 创建项目,画出你项目的目录树
  2. 进阶题(难度⭐⭐):在 components/ 下创建两级子目录的组件,验证自动导入时的命名规则(如 components/shop/product/Card.vue 的标签名是什么)
  3. 挑战题(难度⭐⭐⭐):配置 nuxt.config.ts 的 routeRules,让首页预渲染、商品页 ISR 60 秒、管理页 CSR,并验证效果

---|

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏