关于 nuxt-core
面向 Nuxt 4 应用开发者的核心实践指南,覆盖项目结构、配置、路由、SEO 和错误处理。还提供进阶主题的参考文件指引与常见问题排查建议。
主要功能
- 01Nuxt 4 项目结构与配置
- 02文件式路由和中间件
- 03页面 SEO 与元数据
- 04运行时配置管理
- 05错误处理与故障排查
适用场景
- 01初始化 Nuxt 4 项目
- 02实现动态路由与访问控制
- 03配置页面搜索元数据
- 04排查构建和路由问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill nuxt-core安装后在 Claude Code 中输入/nuxt-core确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
templates/app.vueinit-nuxt-v4.shnuxt.config.ts详细介绍
Nuxt 4 核心基础知识
Nuxt 4 应用的项目设置、配置、路由、SEO 和错误处理。
快速参考
版本要求
| Package | 最低版本 | 推荐版本 |
|---|---|---|
| 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 |
关键命令
# Create new project
bunx nuxi@latest init my-app
# Development
bun run dev
# Build for production
bun run build
# Preview production build
bun run preview
# Type checking
bun run postinstall # Generates .nuxt directory
bunx nuxi typecheck
# Add a page/component/composable
bunx nuxi add page about
bunx nuxi add component MyButton
bunx nuxi add composable useAuth
安全安装
bunx nuxi init 等脚手架工具会下载并执行远程代码。运行前,请遵循供应链安全最佳实践:
- 阻止安装后脚本 —
npm config set ignore-scripts true(或使用 Bun:默认禁用) - 冷却期 — 等待 7 天,让社区审核新版本
- 安装前审计 — 运行
socket package score npm <pkg>,或使用socket npm install <pkg>检查软件包
加载 dependency-upgrade 技能,了解完整的安全配置,包括 Socket CLI 集成、冷却期设置、锁文件验证和 CI 执行。
目录结构(Nuxt v4)
my-nuxt-app/
├── app/ # Default srcDir in v4
│ ├── assets/ # Build-processed assets (CSS, images)
│ ├── components/ # Auto-imported Vue components
│ ├── composables/ # Auto-imported composables
│ ├── layouts/ # Layout components
│ ├── middleware/ # Route middleware
│ ├── pages/ # File-based routing
│ ├── plugins/ # Nuxt plugins
│ ├── utils/ # Auto-imported utility functions
│ ├── app.vue # Main app component
│ ├── app.config.ts # App-level runtime config
│ ├── error.vue # Error page component
│ └── router.options.ts # Router configuration
│
├── server/ # Server-side code (Nitro)
│ ├── api/ # API endpoints
│ ├── middleware/ # Server middleware
│ ├── plugins/ # Nitro plugins
│ ├── routes/ # Server routes
│ └── utils/ # Server utilities
│
├── public/ # Static assets (served from root)
├── shared/ # Shared code (app + server)
├── content/ # Nuxt Content files (if using)
├── layers/ # Nuxt layers
├── modules/ # Local modules
├── .nuxt/ # Generated files (git ignored)
├── .output/ # Build output (git ignored)
├── nuxt.config.ts # Nuxt configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies
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({
// Enable Nuxt 4 features
future: {
compatibilityVersion: 4
},
// Development tools
devtools: { enabled: true },
// Modules
modules: [
'@nuxt/ui',
'@nuxt/content',
'@nuxt/image'
],
// Runtime config (environment variables)
runtimeConfig: {
// Server-only (not exposed to client)
apiSecret: process.env.API_SECRET,
databaseUrl: process.env.DATABASE_URL,
// Public (client + server)
public: {
apiBase: process.env.API_BASE || 'https://api.example.com',
appName: 'My App'
}
},
// App config
app: {
head: {
title: 'My Nuxt App',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
]
}
},
// Nitro config (server)
nitro: {
preset: 'cloudflare-pages'
},
// TypeScript
typescript: {
strict: true,
typeCheck: true
}
})
运行时配置用法
// In composables or components
const config = useRuntimeConfig()
// Public values (client + server)
const apiBase = config.public.apiBase
// Server-only values (only in server/)
const apiSecret = config.apiSecret // undefined on client!
关键规则:在生产环境中,始终使用 useRuntimeConfig() 而非 process.env 来获取环境变量。
应用配置与运行时配置
| 特性 | 应用配置 | 运行时配置 |
|---|---|---|
| 位置 | app.config.ts | nuxt.config.ts |
| 热重载 | 是 | 否 |
| 密钥 | 否 | 是(仅服务端) |
| 使用场景 | UI 设置、主题 | API 密钥、URL |
// app/app.config.ts - UI settings (hot-reloadable)
export default defineAppConfig({
theme: {
primaryColor: '#3490dc'
},
ui: {
rounded: 'lg'
}
})
// Usage
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/* (catch-all)
动态路由
<script setup lang="ts">
const route = useRoute()
// Get route params
const userId = route.params.id
// Reactive (updates when route changes)
const userId = computed(() => route.params.id)
// Fetch user data
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) // Go back in history
}
// With options
const goToLogin = () => {
navigateTo('/login', {
replace: true, // Replace current history entry
external: false // Internal navigation
})
}
</script>
<template>
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink :to="`/users/${user.id}`">View User</NuxtLink>
<NuxtLink to="/dashboard" prefetch>Dashboard</NuxtLink>
<NuxtLink to="/admin" :prefetch="false">Admin</NuxtLink>
</template>
路由中间件
// app/middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
全局中间件
// app/middleware/analytics.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Runs on every route change
if (import.meta.client) {
window.gtag?.('event', 'page_view', {
page_path: to.path
})
}
})
页面元信息
<script setup lang="ts">
definePageMeta({
title: 'Dashboard',
middleware: ['auth'],
layout: 'admin',
pageTransition: { name: 'fade' },
keepalive: true
})
</script>
SEO 与 Meta 标签
useSeoMeta(推荐)
<script setup lang="ts">
useSeoMeta({
title: 'My Page Title',
description: 'Page description for search engines',
ogTitle: 'My Page Title',
ogDescription: 'Page description',
ogImage: 'https://example.com/og-image.jpg',
ogUrl: 'https://example.com/my-page',
twitterCard: 'summary_large_image',
twitterTitle: 'My Page Title',
twitterDescription: 'Page description',
twitterImage: 'https://example.com/og-image.jpg'
})
</script>
useHead(控制更灵活)
<script setup lang="ts">
useHead({
title: 'My Page Title',
meta: [
{ name: 'description', content: 'Page description' },
{ property: 'og:title', content: 'My Page Title' }
],
link: [
{ rel: 'canonical', href: 'https://example.com/my-page' }
],
script: [
{ src: 'https://example.com/script.js', defer: true }
]
})
</script>
动态 Meta 标签
<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' // "Page Title | My App"
}
}
})
错误处理
错误页面
<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">Go Home</button>
</div>
</template>
错误边界(组件级)
<template>
<NuxtErrorBoundary @error="handleError">
<template #error="{ error, clearError }">
<div class="error-container">
<h2>Something went wrong</h2>
<p>{{ error.message }}</p>
<button @click="clearError">Try again</button>
</div>
</template>
<MyComponent />
</NuxtErrorBoundary>
</template>
<script setup>
const handleError = (error: Error) => {
console.error('Component error:', error)
// Send to error tracking service
}
</script>
抛出错误
// In pages or components
throw createError({
statusCode: 404,
statusMessage: 'Page Not Found',
fatal: true // Shows error page, stops rendering
})
// Non-fatal error (shows inline)
throw createError({
statusCode: 400,
message: 'Invalid input'
})
API 错误处理
const { data, error } = await useFetch('/api/users')
if (error.value) {
// Handle error gracefully
showError({
statusCode: error.value.statusCode,
message: error.value.message
})
}
常见反模式
使用 process.env 而非运行时配置
// WRONG - Won't work in production!
const apiUrl = process.env.API_URL
// CORRECT
const config = useRuntimeConfig()
const apiUrl = config.public.apiBase
缺少中间件守卫
// WRONG - No return, middleware continues
export default defineNuxtRouteMiddleware((to) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
navigateTo('/login') // Missing return!
}
})
// CORRECT
export default defineNuxtRouteMiddleware((to) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login') // Return stops middleware chain
}
})
非响应式路由参数
// WRONG - Not reactive
const userId = route.params.id
// CORRECT - Reactive
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()或不返回任何内容
Meta 标签未更新:
- 使用响应式值:
title: () => post.value?.title - 确保在
<script setup>中调用useSeoMeta
相关技能
- 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
评论
支持 Markdown