Nuxt.js项目结构 #

一、目录概览 #

一个标准的 Nuxt 3 项目结构如下:

text
my-nuxt-app/
├── .nuxt/              # 自动生成的构建文件
├── .output/            # 构建输出目录
├── app.vue             # 应用入口组件
├── nuxt.config.ts      # Nuxt 配置文件
├── app.config.ts       # 应用配置文件
├── error.vue           # 错误页面
├── pages/              # 页面路由
├── components/         # 组件目录
├── layouts/            # 布局组件
├── composables/        # 组合式函数
├── plugins/            # 插件目录
├── modules/            # 模块目录
├── middleware/         # 路由中间件
├── server/             # 服务端代码
├── assets/             # 需要构建的静态资源
├── public/             # 静态文件目录
├── utils/              # 工具函数
└── types/              # TypeScript 类型定义

二、核心文件 #

2.1 app.vue #

app.vue 是应用的入口组件,是 Nuxt 应用的根组件。

vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
  • <NuxtLayout>:渲染当前页面使用的布局
  • <NuxtPage>:渲染当前页面的组件

2.2 nuxt.config.ts #

nuxt.config.ts 是 Nuxt 的核心配置文件:

typescript
export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: [
    '@nuxtjs/tailwindcss'
  ],
  app: {
    head: {
      title: 'My App',
      meta: [
        { name: 'description', content: 'My amazing Nuxt application' }
      ]
    }
  },
  runtimeConfig: {
    public: {
      apiBase: '/api'
    }
  }
})

2.3 app.config.ts #

app.config.ts 用于定义应用级别的配置,可以在运行时访问:

typescript
export default defineAppConfig({
  title: 'My App',
  theme: {
    primaryColor: 'blue'
  }
})

在组件中使用:

vue
<script setup>
const appConfig = useAppConfig()
console.log(appConfig.title)
</script>

2.4 error.vue #

error.vue 用于显示错误页面:

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

<script setup>
const props = defineProps({
  error: Object
})

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

三、路由相关目录 #

3.1 pages/ #

pages/ 目录用于创建页面路由。Nuxt 会根据文件结构自动生成路由。

text
pages/
├── index.vue           → /
├── about.vue           → /about
├── blog/
│   ├── index.vue       → /blog
│   ├── [id].vue        → /blog/:id
│   └── category/
│       └── [slug].vue  → /blog/category/:slug
└── user/
    └── [id]/
        └── profile.vue → /user/:id/profile

动态路由 #

使用方括号创建动态路由:

vue
<template>
  <div>
    <h1>文章 ID: {{ route.params.id }}</h1>
  </div>
</template>

<script setup>
const route = useRoute()
</script>

路由组 #

使用括号创建路由组(不影响 URL):

text
pages/
├── (marketing)/
│   ├── about.vue       → /about
│   └── contact.vue     → /contact
└── (shop)/
    ├── products.vue    → /products
    └── cart.vue        → /cart

3.2 layouts/ #

layouts/ 目录用于定义页面布局:

vue
<template>
  <div class="layout">
    <header>
      <nav>...</nav>
    </header>
    <main>
      <slot />
    </main>
    <footer>...</footer>
  </div>
</template>

在页面中使用指定布局:

vue
<script setup>
definePageMeta({
  layout: 'custom'
})
</script>

3.3 middleware/ #

middleware/ 目录用于存放路由中间件:

typescript
export default defineNuxtRouteMiddleware((to, from) => {
  const isAuthenticated = useState('authenticated')
  
  if (!isAuthenticated.value) {
    return navigateTo('/login')
  }
})

在页面中使用:

vue
<script setup>
definePageMeta({
  middleware: 'auth'
})
</script>

四、组件相关目录 #

4.1 components/ #

components/ 目录用于存放 Vue 组件,组件会自动导入:

text
components/
├── AppHeader.vue       → <AppHeader />
├── AppFooter.vue       → <AppFooter />
├── blog/
│   ├── Card.vue        → <BlogCard />
│   └── List.vue        → <BlogList />
└── ui/
    ├── Button.vue      → <UiButton />
    └── Input.vue       → <UiInput />

组件命名规则:

  • 目录名作为前缀
  • 文件名转换为 PascalCase
  • 例如 components/blog/Card.vue<BlogCard />

4.2 composables/ #

composables/ 目录用于存放组合式函数,会自动导入:

typescript
export const useCounter = () => {
  const count = ref(0)
  const increment = () => count.value++
  const decrement = () => count.value--
  
  return {
    count,
    increment,
    decrement
  }
}

在组件中使用:

vue
<script setup>
const { count, increment, decrement } = useCounter()
</script>

4.3 utils/ #

utils/ 目录用于存放工具函数,会自动导入:

typescript
export const formatDate = (date: string) => {
  return new Date(date).toLocaleDateString('zh-CN')
}

export const slugify = (text: string) => {
  return text.toLowerCase().replace(/\s+/g, '-')
}

五、服务端目录 #

5.1 server/ #

server/ 目录用于存放服务端代码:

text
server/
├── api/
│   ├── users.ts        → /api/users
│   └── blog/
│       ├── index.ts    → /api/blog
│       └── [id].ts     → /api/blog/:id
├── routes/
│   └── sitemap.ts      → /sitemap.xml
├── middleware/
│   └── auth.ts         # 服务端中间件
└── plugins/
    └── db.ts           # 服务端插件

API 路由 #

typescript
export default defineEventHandler((event) => {
  return {
    message: 'Hello API'
  }
})

服务端中间件 #

typescript
export default defineEventHandler((event) => {
  const token = getHeader(event, 'authorization')
  
  if (!token) {
    throw createError({
      statusCode: 401,
      message: 'Unauthorized'
    })
  }
})

六、资源目录 #

6.1 assets/ #

assets/ 目录用于存放需要构建处理的静态资源:

text
assets/
├── css/
│   └── main.css
├── images/
│   └── logo.png
└── fonts/
    └── custom.woff2

在组件中引用:

vue
<template>
  <img src="~/assets/images/logo.png" />
</template>

<style>
@import '~/assets/css/main.css';
</style>

6.2 public/ #

public/ 目录用于存放不需要构建的静态文件:

text
public/
├── favicon.ico
├── robots.txt
└── images/
    └── og-image.png

直接通过 URL 访问:/favicon.ico

七、扩展目录 #

7.1 plugins/ #

plugins/ 目录用于存放 Nuxt 插件:

typescript
export default defineNuxtPlugin((nuxtApp) => {
  return {
    provide: {
      formatPrice: (price: number) => `¥${price.toFixed(2)}`
    }
  }
})

在组件中使用:

vue
<script setup>
const { $formatPrice } = useNuxtApp()
</script>

7.2 modules/ #

modules/ 目录用于存放本地模块:

typescript
export default defineNuxtModule({
  meta: {
    name: 'my-module',
    configKey: 'myModule'
  },
  setup(options, nuxt) {
    // 模块逻辑
  }
})

7.3 types/ #

types/ 目录用于存放 TypeScript 类型定义:

typescript
declare module 'nuxt/schema' {
  interface NuxtConfig {
    myModule?: MyModuleOptions
  }
}

export interface MyModuleOptions {
  enabled: boolean
}

八、构建输出目录 #

8.1 .nuxt/ #

.nuxt/ 目录是 Nuxt 自动生成的,包含:

  • 类型定义
  • 构建配置
  • 生成的路由
  • 开发服务器文件

注意:不要手动修改此目录,也不要提交到版本控制。

8.2 .output/ #

.output/ 目录是构建输出,包含:

  • 服务端代码
  • 客户端代码
  • 静态文件

注意:此目录会在每次构建时重新生成。

九、最佳实践 #

9.1 目录组织建议 #

text
src/
├── pages/          # 按功能模块组织
│   ├── (auth)/
│   │   ├── login.vue
│   │   └── register.vue
│   └── (dashboard)/
│       ├── index.vue
│       └── settings.vue
├── components/     # 按功能分类
│   ├── common/     # 通用组件
│   ├── layout/     # 布局组件
│   └── features/   # 功能组件
├── composables/    # 按功能分类
│   ├── useAuth.ts
│   └── useCart.ts
└── server/
    └── api/        # 按模块分类
        ├── auth/
        └── products/

9.2 命名规范 #

类型 命名规范 示例
页面 kebab-case user-profile.vue
组件 PascalCase UserProfile.vue
组合式函数 camelCase + use前缀 useAuth.ts
工具函数 camelCase formatDate.ts
类型 PascalCase User.ts

十、总结 #

本章介绍了 Nuxt.js 项目的目录结构:

  • pages/:页面路由
  • components/:Vue 组件
  • layouts/:布局组件
  • composables/:组合式函数
  • server/:服务端代码
  • assets/public/:静态资源
  • plugins/modules/:扩展功能

理解项目结构是开发 Nuxt.js 应用的基础,合理组织代码可以提高开发效率和代码可维护性。

最后更新:2026-03-28