Nuxt4核心框架基础 nuxt-core

这个技能专注于Nuxt 4框架的核心开发和配置,涵盖项目初始化、配置文件设置、文件路由实现、SEO优化和错误处理。适用于前端开发者快速构建现代化的Vue应用,提高开发效率和性能。关键词:Nuxt 4, Vue 3, 前端开发, 配置, 路由, SEO, 错误处理, 框架

前端开发 0 次安装 0 次浏览 更新于 3/7/2026

name: nuxt-core description: | Nuxt 4 核心框架基础:项目设置、配置、路由、 SEO、错误处理和目录结构。

使用场景:创建新的 Nuxt 4 项目,配置 nuxt.config.ts, 设置路由和中间件,使用 useHead/useSeoMeta 实现 SEO, 通过 error.vue 和 NuxtErrorBoundary 处理错误,或理解 Nuxt 4 目录结构。

关键词:Nuxt 4, nuxt.config.ts, 文件路由, pages 目录, definePageMeta, useHead, useSeoMeta, error.vue, NuxtErrorBoundary, 中间件, navigateTo, NuxtLink, app 目录, 运行时配置 license: MIT metadata: version: 4.0.0 author: Claude Skills Maintainers category: Framework framework: Nuxt framework-version: 4.x last-verified: 2025-12-28

Nuxt 4 核心基础

Nuxt 4 应用程序的项目设置、配置、路由、SEO 和错误处理。

快速参考

版本要求

最低 推荐
nuxt 4.0.0 4.2.x
vue 3.5.0 3.5.x
nitro 2.10.0 2.12.x
vite 6.0.0 6.2.x
typescript 5.0.0 5.x

关键命令

# 创建新项目
bunx nuxi@latest init my-app

# 开发
bun run dev

# 构建生产版本
bun run build

# 预览生产构建
bun run preview

# 类型检查
bun run postinstall  # 生成 .nuxt 目录
bunx nuxi typecheck

# 添加页面/组件/可组合项
bunx nuxi add page about
bunx nuxi add component MyButton
bunx nuxi add composable useAuth

目录结构 (Nuxt v4)

my-nuxt-app/
├── app/                    # v4 中的默认 srcDir
│   ├── assets/             # 构建处理的资产(CSS、图片)
│   ├── components/         # 自动导入的 Vue 组件
│   ├── composables/        # 自动导入的可组合项
│   ├── layouts/            # 布局组件
│   ├── middleware/         # 路由中间件
│   ├── pages/              # 文件路由
│   ├── plugins/            # Nuxt 插件
│   ├── utils/              # 自动导入的实用函数
│   ├── app.vue             # 主应用组件
│   ├── app.config.ts       # 应用级运行时配置
│   ├── error.vue           # 错误页面组件
│   └── router.options.ts   # 路由器配置
│
├── server/                 # 服务器端代码(Nitro)
│   ├── api/                # API 端点
│   ├── middleware/         # 服务器中间件
│   ├── plugins/            # Nitro 插件
│   ├── routes/             # 服务器路由
│   └── utils/              # 服务器实用工具
│
├── public/                 # 静态资产(从根目录提供)
├── shared/                 # 共享代码(应用 + 服务器)
├── content/                # Nuxt Content 文件(如使用)
├── layers/                 # Nuxt 层
├── modules/                # 本地模块
├── .nuxt/                  # 生成文件(git 忽略)
├── .output/                # 构建输出(git 忽略)
├── nuxt.config.ts          # Nuxt 配置
├── tsconfig.json           # TypeScript 配置
└── package.json            # 依赖项

v4 中的关键变化app/ 目录现在是默认的 srcDir。所有应用代码放在 app/ 中,服务器代码留在 server/

何时加载参考

加载 references/configuration-deep.md 当:

  • 配置高级 nuxt.config.ts 选项
  • 设置模块和插件
  • 自定义 Vite 或 Nitro 配置
  • 配置实验性功能

加载 references/routing-advanced.md 当:

  • 实现复杂路由模式
  • 创建带有身份验证的路由中间件
  • 使用捕获所有路由或可选参数
  • 配置路由器选项

加载 references/plugins-architecture.md 当:

  • 创建 Nuxt 插件
  • 注入全局实用工具或可组合项
  • 集成第三方库
  • 理解插件执行顺序

配置

基本 nuxt.config.ts

export default defineNuxtConfig({
  // 启用 Nuxt 4 功能
  future: {
    compatibilityVersion: 4
  },

  // 开发工具
  devtools: { enabled: true },

  // 模块
  modules: [
    '@nuxt/ui',
    '@nuxt/content',
    '@nuxt/image'
  ],

  // 运行时配置(环境变量)
  runtimeConfig: {
    // 仅服务器端(不暴露给客户端)
    apiSecret: process.env.API_SECRET,
    databaseUrl: process.env.DATABASE_URL,

    // 公共(客户端 + 服务器)
    public: {
      apiBase: process.env.API_BASE || 'https://api.example.com',
      appName: 'My App'
    }
  },

  // 应用配置
  app: {
    head: {
      title: 'My Nuxt App',
      meta: [
        { charset: 'utf-8' },
        { name: 'viewport', content: 'width=device-width, initial-scale=1' }
      ]
    }
  },

  // Nitro 配置(服务器)
  nitro: {
    preset: 'cloudflare-pages'
  },

  // TypeScript
  typescript: {
    strict: true,
    typeCheck: true
  }
})

运行时配置使用

// 在可组合项或组件中
const config = useRuntimeConfig()

// 公共值(客户端 + 服务器)
const apiBase = config.public.apiBase

// 仅服务器端值(仅在 server/ 中)
const apiSecret = config.apiSecret  // 在客户端为 undefined!

关键规则:在生产环境中,始终使用 useRuntimeConfig() 而不是 process.env 处理环境变量。

应用配置 vs 运行时配置

特性 应用配置 运行时配置
位置 app.config.ts nuxt.config.ts
热重载
机密 是(仅服务器端)
使用场景 UI 设置、主题 API 密钥、URL
// app/app.config.ts - UI 设置(可热重载)
export default defineAppConfig({
  theme: {
    primaryColor: '#3490dc'
  },
  ui: {
    rounded: 'lg'
  }
})

// 使用
const appConfig = useAppConfig()
const color = appConfig.theme.primaryColor

路由

文件路由

app/pages/
├── index.vue              → /
├── about.vue              → /about
├── users/
│   ├── index.vue          → /users
│   └── [id].vue           → /users/:id
└── blog/
    ├── index.vue          → /blog
    ├── [slug].vue         → /blog/:slug
    └── [...slug].vue      → /blog/*(捕获所有)

动态路由

<!-- app/pages/users/[id].vue -->
<script setup lang="ts">
const route = useRoute()

// 获取路由参数
const userId = route.params.id

// 响应式(路由变化时更新)
const userId = computed(() => route.params.id)

// 获取用户数据
const { data: user } = await useFetch(`/api/users/${userId.value}`)
</script>

<template>
  <div>
    <h1>{{ user?.name }}</h1>
  </div>
</template>

导航

<script setup>
const goToUser = (id: string) => {
  navigateTo(`/users/${id}`)
}

const goBack = () => {
  navigateTo(-1)  // 返回历史记录
}

// 带选项
const goToLogin = () => {
  navigateTo('/login', {
    replace: true,  // 替换当前历史记录条目
    external: false // 内部导航
  })
}
</script>

<template>
  <!-- 声明式导航 -->
  <NuxtLink to="/about">关于</NuxtLink>
  <NuxtLink :to="`/users/${user.id}`">查看用户</NuxtLink>

  <!-- 预取(默认:悬停) -->
  <NuxtLink to="/dashboard" prefetch>仪表盘</NuxtLink>

  <!-- 不预取 -->
  <NuxtLink to="/admin" :prefetch="false">管理员</NuxtLink>
</template>

路由中间件

// app/middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const { isAuthenticated } = useAuth()

  if (!isAuthenticated.value) {
    return navigateTo('/login')
  }
})
<!-- app/pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
  middleware: 'auth'
})
</script>

全局中间件

// app/middleware/analytics.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  // 在每次路由变化时运行
  if (import.meta.client) {
    window.gtag?.('event', 'page_view', {
      page_path: to.path
    })
  }
})

页面元数据

<script setup lang="ts">
definePageMeta({
  title: '仪表盘',
  middleware: ['auth'],
  layout: 'admin',
  pageTransition: { name: 'fade' },
  keepalive: true
})
</script>

SEO 和元标签

useSeoMeta(推荐)

<script setup lang="ts">
useSeoMeta({
  title: '我的页面标题',
  description: '搜索引擎的页面描述',
  ogTitle: '我的页面标题',
  ogDescription: '页面描述',
  ogImage: 'https://example.com/og-image.jpg',
  ogUrl: 'https://example.com/my-page',
  twitterCard: 'summary_large_image',
  twitterTitle: '我的页面标题',
  twitterDescription: '页面描述',
  twitterImage: 'https://example.com/og-image.jpg'
})
</script>

useHead(更多控制)

<script setup lang="ts">
useHead({
  title: '我的页面标题',
  meta: [
    { name: 'description', content: '页面描述' },
    { property: 'og:title', content: '我的页面标题' }
  ],
  link: [
    { rel: 'canonical', href: 'https://example.com/my-page' }
  ],
  script: [
    { src: 'https://example.com/script.js', defer: true }
  ]
})
</script>

动态元标签

<script setup lang="ts">
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)

useSeoMeta({
  title: () => post.value?.title,
  description: () => post.value?.excerpt,
  ogImage: () => post.value?.image
})
</script>

标题模板

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      titleTemplate: '%s | My App'  // "页面标题 | 我的应用"
    }
  }
})

错误处理

错误页面

<!-- app/error.vue -->
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps<{
  error: NuxtError
}>()

const handleError = () => {
  clearError({ redirect: '/' })
}
</script>

<template>
  <div class="error-page">
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.message }}</p>
    <button @click="handleError">返回首页</button>
  </div>
</template>

错误边界(组件级)

<template>
  <NuxtErrorBoundary @error="handleError">
    <template #error="{ error, clearError }">
      <div class="error-container">
        <h2>出错了</h2>
        <p>{{ error.message }}</p>
        <button @click="clearError">重试</button>
      </div>
    </template>

    <!-- 您的组件内容 -->
    <MyComponent />
  </NuxtErrorBoundary>
</template>

<script setup>
const handleError = (error: Error) => {
  console.error('组件错误:', error)
  // 发送到错误跟踪服务
}
</script>

抛出错误

// 在页面或组件中
throw createError({
  statusCode: 404,
  statusMessage: '页面未找到',
  fatal: true  // 显示错误页面,停止渲染
})

// 非致命错误(内联显示)
throw createError({
  statusCode: 400,
  message: '输入无效'
})

API 错误处理

const { data, error } = await useFetch('/api/users')

if (error.value) {
  // 优雅处理错误
  showError({
    statusCode: error.value.statusCode,
    message: error.value.message
  })
}

常见反模式

使用 process.env 替代运行时配置

// 错误 - 在生产环境中无效!
const apiUrl = process.env.API_URL

// 正确
const config = useRuntimeConfig()
const apiUrl = config.public.apiBase

缺少中间件守卫

// 错误 - 无返回,中间件继续
export default defineNuxtRouteMiddleware((to) => {
  const { isAuthenticated } = useAuth()
  if (!isAuthenticated.value) {
    navigateTo('/login')  // 缺少返回!
  }
})

// 正确
export default defineNuxtRouteMiddleware((to) => {
  const { isAuthenticated } = useAuth()
  if (!isAuthenticated.value) {
    return navigateTo('/login')  // 返回停止中间件链
  }
})

非响应式路由参数

// 错误 - 非响应式
const userId = route.params.id

// 正确 - 响应式
const userId = computed(() => route.params.id)

故障排除

构建错误 / 类型错误:

rm -rf .nuxt .output node_modules/.vite && bun install && bun run dev

路由未找到:

  • 检查文件是否在 app/pages/(而非根 pages/
  • 验证文件扩展名为 .vue
  • 检查动态参数 [id].vue 中的拼写错误

中间件不运行:

  • 确保全局中间件文件有 .global.ts 后缀
  • 检查 definePageMeta({ middleware: 'name' }) 与文件名匹配
  • 验证中间件返回 navigateTo() 或什么都不返回

元标签不更新:

  • 使用响应式值:title: () => post.value?.title
  • 确保 useSeoMeta<script setup> 中调用

相关技能

  • nuxt-data:可组合项、数据获取、状态管理
  • nuxt-server:服务器路由、API 模式、数据库集成
  • nuxt-production:性能、测试、部署
  • nuxt-ui-v4:Nuxt UI 组件库

可用模板

查看 templates/ 目录:

  • 生产就绪的 nuxt.config.ts
  • 结构良好的 app.vue
  • 中间件示例

版本:4.0.0 | 最后更新:2025-12-28 | 许可证:MIT