首页
/ 深度解析 Nuxt 目录结构:组织全栈 Vue 应用的完整指南

深度解析 Nuxt 目录结构:组织全栈 Vue 应用的完整指南

2026-09-04 22:55:53作者:齐添朝

本文基于 Nuxt 官方文档 docs/2.directory-structure/index.md 及其配套子文档,系统讲解一个 Nuxt 应用中各个标准目录(app/server/shared/public/modules/layers/ 等)的职责、约定与自动注册机制,并结合当前仓库中的 monorepo 源码组织与测试夹具,说明这些目录约定在框架内部是如何落地和被验证的。读完本文,你将能够从零规划一个结构清晰、符合 Nuxt 惯例的全栈应用目录,并理解每个目录背后的自动导入、路由生成与构建行为。

1. 目录结构总览

Nuxt 应用有一套被刻意设计为“易于理解且一致使用”的目录结构:目录即约定,文件放在正确的位置,就会被自动扫描、自动导入或自动注册为路由。官方文档 目录结构总览 描述的完整布局如下(综合各子文档示例整理):

-| project/
---| nuxt.config.ts          # 主配置文件(确定项目根目录的标志)
---| .nuxtrc                 # 可选:扁平语法的配置
---| .nuxtignore             # 可选:构建阶段忽略文件
---| .env                    # 可选:环境变量
---| app/                    # 应用主目录(客户端 + SSR 代码)
-----| app.vue               # 应用根组件
-----| app.config.ts         # 响应式应用配置
-----| error.vue             # 错误页
-----| assets/               # 由构建工具(Vite/webpack)处理的资源
-----| components/           # 自动导入的 Vue 组件
-----| composables/          # Vue composables
-----| layouts/              # 页面布局组件
-----| middleware/            # 路由级前端中间件
-----| pages/                # 基于文件的路由
-----| plugins/               # Nuxt 应用插件
-----| utils/                 # 应用内工具函数
---| public/                 # 静态资源,原样按根路径提供
---| server/                 # 服务端(Nitro)代码
-----| api/                   # /api 前缀的 API 路由
-----| routes/                # 不带 /api 前缀的服务路由
-----| middleware/             # 服务端中间件
-----| plugins/                # 服务端插件
-----| utils/                 # 服务端工具函数
-----| types/                 # 仅在服务端自动导入的类型
---| shared/                 # 应用与服务端共享的代码
-----| utils/                 # 两端自动导入的工具函数
-----| types/                 # 两端自动导入的类型
---| modules/                # 本地模块(自动注册)
---| layers/                 # 本地层(自动注册)
---| content/                # 文件式 CMS(由 Nuxt Content 模块启用)
---| test/                   # 应用测试(unit/nuxt/e2e)
---| .nuxt/                  # 开发期生成目录(应加入 .gitignore)
---| .output/                # 生产构建输出目录(应加入 .gitignore)

两个关键的“判定性”事实:

  • 根目录:Nuxt 应用的根目录就是包含 nuxt.config.ts 的目录,该文件是应用的配置入口;
  • app/ 主目录:Nuxt 4 将应用代码统一收敛在 app/ 目录中(而非 Nuxt 3 时代的根目录 pages/components/),其中 pages/ 等子目录的存在与否会直接影响依赖是否被引入——例如没有 pages/ 时不会引入 vue-router。

当前仓库本身就遵循并验证了这一结构:仓库根的 nuxt.config.ts 定义了 Nuxt 项目自身,test/fixtures/basic/ 是一个包含 app/server/modules/layers/custom-public/ 的完整测试应用,用于在 CI 中验证上述目录约定的实际行为。

2. 根目录与配置文件

2.1 nuxt.config.ts

应用的主配置文件,扩展名可以是 .js.ts.mjsdefineNuxtConfig 辅助函数全局可用,无需导入;也可以显式从 nuxt/config 导入(见 nuxt.config.ts 文档):

export default defineNuxtConfig({
  // 我的 Nuxt 配置
})

Nuxt 在检测到主配置文件、.env.nuxtignore.nuxtrc 变化时会执行完整重启,因此这些文件变更不会通过 HMR 热更新。

2.2 .nuxtrc

.nuxtrc 提供基于 unjs/rc9扁平语法配置,适合全局性配置。示例(摘自 .nuxtrc 文档):

# 禁用 SSR
ssr=false

# 配置 @nuxt/devtools
devtools.enabled=true

# 添加 Nuxt 模块
modules[]=@nuxt/image
modules[]=nuxt-security

# 模块安装状态(由 Nuxt 自动写入,勿手动修改)
setups.@nuxt/test-utils="3.23.0"

优先级为:nuxt.config > 项目级 .nuxtrc > 全局 ~/.nuxtrc(macOS/Linux)或 C:\Users\{username}\.nuxtrc(Windows)。Nuxt 会自动维护其中的 setups 段落来跟踪模块的安装与升级状态,该段落不应手工编辑。

2.3 .nuxtignore

.nuxtignore 让 Nuxt 在构建阶段忽略根目录中的指定文件,其规则与 .gitignore 完全相同(每行一个 glob 模式)。官方示例:

# 忽略布局 app/layouts/foo.vue
app/layouts/foo.vue
# 忽略名字以 -ignore.vue 结尾的布局
app/layouts/*-ignore.vue

# 忽略页面 app/pages/bar.vue
app/pages/bar.vue
# 忽略 ignore 文件夹内的页面
app/pages/ignore/*.vue

# 忽略 foo 文件夹下的中间件,但保留 foo/bar.js
app/middleware/foo/*.js
!app/middleware/foo/bar.js

此外还可以在 nuxt.config 中用 ignoreOptionsignorePrefixignore 配置项实现同样的忽略行为(见 .nuxtignore 文档)。

3. app/ 应用目录

app/ 是 Nuxt 应用的主目录,包含应用前端的全部约定目录与三个特殊文件。

3.1 app.vue 根组件

app.vue 是应用的根组件(app.vue 文档)。它的三种典型用法:

<!-- 最小用法:没有 pages/ 时,app.vue 就是整个应用 -->
<template>
  <h1>Hello World!</h1>
</template>
<!-- 配合 pages/:必须用 <NuxtPage /> 渲染当前页面 -->
<template>
  <NuxtPage />
</template>
<!-- 配合 layouts/:用 <NuxtLayout /> 包裹 <NuxtPage /> -->
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

注意:app.vue 中引入的任何 JS 与 CSS 都是全局的,会被包含进每一个页面;存在 pages/app.vue 是可选的(Nuxt 会自动提供默认实现),但你仍可自行定制。

3.2 app.config.ts 响应式应用配置

app.config.ts(扩展名可为 .ts/.js/.mjs)暴露一份响应式的应用内配置,可在运行时通过插件或生命周期更新,并支持 HMR(app.config 文档):

export default defineAppConfig({
  theme: {
    primaryColor: '#ababab',
  },
})

在 SSR 与浏览器中均可通过 useAppConfig() 访问,并用 updateAppConfig() 在运行时更新:

<script setup>
const appConfig = useAppConfig() // { foo: 'bar' }
const newAppConfig = { foo: 'baz' }

updateAppConfig(newAppConfig)

console.log(appConfig) // { foo: 'baz' }
</script>

约束与限制:

  • 绝不能存放密钥——该配置会暴露到客户端 bundle;
  • 由于 app.config.ts 与 Nitro 共享处理流程,不能在其中直接导入 Vue 组件,部分自动导入在 Nitro 上下文也不可用;
  • 完整推断的类型只在应用代码中可用;在 server/shared/nuxt.config 中,app.config 的键类型化为 unknown。需要跨上下文类型时可扩展 SharedAppConfig/AppConfigInput/AppConfig 接口(均通过 declare module 'nuxt/schema' 声明合并);
  • 层(layers)之间合并 app.config 时采用基于 defu 函数合并器的自定义策略:数组值可通过返回数组的函数自定义合并行为,但该函数合并器只能用于扩展层、不能用于主项目的 app.config

3.3 error.vue 错误页

运行时出现意外错误时,error.vue 用于覆盖默认错误页并友好地展示错误(error.vue 文档):

<script setup lang="ts">
import type { NuxtError } from '#app'

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

<template>
  <div>
    <h1>{{ error.status }}</h1>
    <NuxtLink to="/">返回首页</NuxtLink>
  </div>
</template>

该文件接收唯一的 error prop,其结构为:

interface NuxtError {
  status: number
  fatal: boolean
  unhandled: boolean
  statusText?: string
  data?: unknown
  cause?: unknown
}

要点:它不是路由,不应放在 pages/ 中,也不要用 definePageMeta;但可以通过 NuxtLayout 组件使用布局。自定义错误字段应放在 data 里(如 throw createError({ status: 404, statusText: 'Page Not Found', data: { myCustomField: true } })),否则会被丢弃。

3.4 pages/ 基于文件的路由

pages/ 目录中每个 Vue 组件都会被自动注册为一条路由(pages 文档):

  • app/pages/index.vue 映射到 /;使用 .vue/.js/.jsx/.mjs/.ts/.tsx 等 Nuxt 支持的有效扩展名均可;
  • 该目录可选:不存在时不会引入 vue-router(适合落地页);要强制启用可设置 pages: true
  • 页面必须有单一根元素(HTML 注释也算元素),否则客户端路由切换时转场会失败。

动态路由:方括号即参数,双方括号为可选参数,[...] 为全捕获路由:

-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue          # 匹配 /users-admins/123
<template>
  <p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>

[[slug]].vue 同时匹配 //test[...slug].vue 匹配该路径下的所有路由(如 /hello/world$route.params.slug["hello", "world"])。访问参数可经 $route(Options API)或 useRoute()(组合式 API)。

路由分组:用括号目录 (marketing)/ 分组不影响 URL 结构;从 v4.3 起分组信息自动写入 route.meta.groups,可在组件中做条件判断。

definePageMeta 页面元数据:编译器宏,可定义 aliaskeepalivekeylayoutlayoutTransition/pageTransitionmiddlewarenamepathprops 等特殊元数据;嵌套路由的 meta 会合并为单一对象。它不能引用响应式数据或有副作用的函数,但可引用导入绑定与局部纯函数;嵌套目录中 parent/child.vue + parent.vue 会生成父子路由,需在内层模板插入 <NuxtPage>

导航:声明式用内置的 <NuxtLink>(无需导入);编程式用 navigateTo(),务必 await 或返回其结果:

<script setup lang="ts">
const name = ref('')

function navigate () {
  return navigateTo({ path: '/search', query: { name: name.value } })
}
</script>

客户端/服务端页面.client.vue 后缀的页面不在服务端渲染任何内容;.server.vue 后缀的页面由服务端组件自动渲染,渲染代码不进入客户端 bundle(必须有单一根元素)。

pages/ 目录:通过 Nuxt 层实现页面分组,例如在 nuxt.configextends: ['./some-app'],让 some-app/pages/ 的页面参与主应用路由。

3.5 components/ 组件目录

components/ 中的组件(以及模块注册的组件)会被自动导入(components 文档)。组件名由路径决定,重复段被去除:components/base/foo/Button.vue<BaseFooButton />;分组目录加括号 (foo)/ 则不参与命名,得到 <BaseButton />;在 nuxt.config 中把 pathPrefix: false 可只按文件名注册(Nuxt 2 风格)。

核心用法速览:

  • 动态组件<component :is="..."> 需要用 Vue 的 resolveComponent(参数必须是字面量字符串),或直接从 #components 导入组件传入 is
  • 懒加载:组件名加 Lazy 前缀,按需加载对应 chunk;
  • 延迟水合hydrate-on-visiblehydrate-on-idlehydrate-on-interactionhydrate-on-media-queryhydrate-afterhydrate-whenhydrate-never 等属性控制组件何时变为可交互,组件水合完成会触发 @hydrated 事件;
  • 全局组件:放在 components/global/ 或使用 .global.vue 后缀;每个全局组件是独立 chunk,不要滥用;
  • 自定义目录与过滤:通过 components: [...] 数组可注册任意目录,支持 pathPrefixprefixpatternignoreextensions 等选项,嵌套目录需先声明(按顺序扫描);
  • 客户端组件.client 后缀使其仅在客户端渲染(只对自动导入与 #components 导入生效);
  • 服务端组件.server 后缀声明仅服务端渲染的“Islands”组件,底层基于 <NuxtIsland>;也可与同名 .client 组件配对,形成服务端/客户端双实现。

3.6 其余约定目录

  • composables/:放置 Vue composables,自动导入(composables 文档);
  • layouts/:包裹页面、避免页面切换时重渲染外围结构的布局组件,配合 <NuxtLayout> 使用(layouts 文档);
  • middleware/:导航到特定路由之前执行的前端路由中间件(middleware 文档);
  • plugins/:在 Nuxt 应用创建时使用的 Vue 插件(plugins 文档);
  • utils/:应用中可在组件、composables、页面内使用的工具函数(utils 文档);
  • assets/:交由构建工具(Vite 或 webpack)处理的网站资源(assets 文档)。

4. public/ 静态资源目录

public/ 中的文件按根路径原样提供,不经过构建流程处理public 文档)。它适合必须保持文件名的文件(如 robots.txt)或基本不会变化的文件(如 favicon.ico):

-| public/
---| favicon.ico
---| og-image.png
---| robots.txt
<script setup lang="ts">
useSeoMeta({
  ogImage: '/og-image.png',
})
</script>

需要区分的是:public/ 是“原样分发”,而 app/assets/ 是“构建处理”——后者会经过打包、压缩与指纹化。

5. server/ 服务端目录

server/ 包含应用的服务端代码,Nuxt 会自动扫描其中的文件并注册 API 与服务端处理器,开发时支持 HMR(server 文档)。每个文件应导出一个用 defineEventHandler()(别名 eventHandler())定义的处理函数,可直接返回 JSON、PromiseResponse 对象:

// server/api/hello.ts → 路由 /api/hello
import { defineEventHandler } from 'nitro/h3'

export default defineEventHandler((event) => {
  return { hello: 'world' }
})

页面中即可通用调用:const { data } = await useFetch('/api/hello')

子目录职责:

目录 职责
server/api/ API 路由,自动加 /api 前缀
server/routes/ 不加 /api 前缀的服务路由(如动态 /sitemap.xml
server/middleware/ 每个请求在任何服务路由之前执行,用于加/检头、记录请求、扩展上下文;不应返回或结束请求
server/plugins/ 注册为 Nitro 插件,扩展 Nitro 运行时行为与生命周期钩子
server/utils/ 服务端自定义工具函数,可被服务端代码自动导入
server/types/ 仅在服务端上下文自动导入的类型(只扫描直接子文件)

常用配方(均来自 server 文档):

  • 动态参数server/api/hello/[name].ts 中用 getRouterParam(event, 'name') 读取;
  • HTTP 方法匹配:文件名加 .get.post.put.delete 等后缀,方法不匹配返回 405;可用 index.[method].ts 构造 API 命名空间;
  • 全捕获路由server/api/foo/[...].ts 兜底所有未匹配请求,[...slug].ts 可命名并读取参数;
  • 请求体readBody(event)(GET 上调用会抛 405),配合 .post.ts 文件;
  • 查询参数getQuery(event)
  • 错误处理:未捕获错误返回 500;其他错误码用 createError({ status, statusText }) 抛出;自定义状态码用 setResponseStatus(event, 202)
  • 运行时配置:服务端用 useRuntimeConfig(),密钥经 .envNUXT_ 前缀变量注入;
  • #server 别名(v4.3+):在 server/ 内任意深度用 import ... from '#server/utils/formatUser' 导入,但不能在客户端代码中使用;
  • 后台任务event.waitUntil(promise) 在响应发出后继续等待异步任务完成。

边界规则:不要在服务端路由/工具中导入 Vue 应用代码,也不要在应用中导入服务端专用代码——两者运行在不同 bundle 与上下文中(原因详见 shared/ 一节)。高级用法还包括 nitro 配置项、createRouter 嵌套路由、sendStream 流式响应、sendRedirect 重定向、fromNodeMiddleware 遗留适配,以及通过 nitro.storage 或 Nitro 插件挂载 Redis 等 unstorage 驱动的存储层。

6. shared/ 共享目录

shared/ 用于存放可同时被 Vue 应用和 Nitro 服务端使用的代码,自 Nuxt v3.14 起可用shared 文档)。

为什么不能混用 Vue 与 Nitro 代码:Nuxt 构建两个彼此独立的 bundle——Vue 应用(客户端 + SSR)与 Nitro 服务端(API 路由、中间件、插件),它们在不同上下文运行。Vue 侧代码依赖 useNuxtApp()useRoute() 等应用上下文;Nitro 侧代码可能依赖 Node API。shared/ 的代码进入两个 bundle,因此不能导入 Vue 代码,也不能导入 Nitro 代码。即使 import type 能在编译期擦除,官方仍建议把跨端类型放在 shared/types/,以匹配应用/服务端/共享三个类型上下文的项目引用划分。

使用方式shared/utils/shared/types/ 中的文件会被两端自动导入(扫描规则与 app/composables/app/utils/ 相同,嵌套子目录不自动导入);其他位置的文件用 #shared 别名显式导入:

// shared/utils/capitalize.ts
export const capitalize = (input: string) => {
  return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}
<!-- app/app.vue:自动导入,无需 import -->
<script setup lang="ts">
const hello = capitalize('hello')
</script>
// server/api/hello.get.ts:同样自动导入
export default defineEventHandler((event) => {
  return { hello: capitalize('hello') }
})
// 需要显式导入时用 #shared 别名
import capitalize from '#shared/capitalize'
import lower from '#shared/formatters/lower'
import upper from '#shared/utils/formatters/upper'

7. modules/ 本地模块目录

modules/ 是存放本地模块的推荐位置,匹配以下模式的文件会被自动注册,无需在 nuxt.config 中再次声明(modules 文档):

  • modules/*/index.ts
  • modules/*.ts

官方示例(模块定义 + 运行时 API 路由):

// modules/hello/index.ts
// `nuxt/kit` 是本地模块可用的子路径导入,无需将 @nuxt/kit 加入项目依赖
import { addComponentsDir, addServerHandler, createResolver, defineNuxtModule } from 'nuxt/kit'

export default defineNuxtModule({
  meta: { name: 'hello' },
  setup () {
    const resolver = createResolver(import.meta.url)

    // 添加 API 路由
    addServerHandler({
      route: '/api/hello',
      handler: resolver.resolve('./runtime/api-route'),
    })

    // 添加组件目录
    addComponentsDir({
      path: resolver.resolve('./runtime/app/components'),
      pathPrefix: true, // 加前缀避免与用户代码或其他模块冲突
    })
  },
})
// modules/hello/runtime/api-route.ts
import { defineEventHandler } from 'nitro/h3'

export default defineEventHandler(() => {
  return { hello: 'world' }
})

执行顺序:先加载 nuxt.config 中声明的模块,再按字母序执行 modules/ 中的本地模块;目录名加数字前缀(1.first-module/2.second-module.ts)可调整顺序。注意:本地模块中会放在 app/ 的文件(组件、页面、composables 等)必须放在 modules/your-module/runtime/app/ 下以保证类型检查正确。

从源码结构看,本地模块机制由 packages/kit 提供——仓库中 packages/kit/src/module/ 目录承载模块注册、生命周期钩子等实现,packages/nuxt 的核心启动流程(packages/nuxt/src/core/)会按上述顺序装配模块。

8. layers/ 层目录

layers/ 用于组织与共享可复用的代码、组件、composables 与配置,其中的层自动注册layers 文档,该能力自 Nuxt v3.12.0 起可用)。典型结构:

-| layers/
---| base/
-----| nuxt.config.ts        # 每个层必须有 nuxt.config.ts(可为空)
-----| app/
-------| components/
---------| BaseButton.vue
-------| composables/
---------| useBase.ts
-----| server/
-------| api/
---------| hello.ts
---| admin/
-----| nuxt.config.ts
-----| app/
-------| pages/
---------| admin.vue
-------| layouts/
---------| admin.vue

要点:

  • 每个层都是一个迷你 Nuxt 应用,可包含 nuxt.config.tsapp.config.tsapp/components|composables|utils|pages|layouts|middleware|plugins/server/shared/
  • 自动别名(v3.16.0+):每层的 srcDir 都有 #layers/[name] 别名,如 import { useAdmin } from '#layers/admin/composables/useAdmin'
  • 优先级:多个层定义同一资源时,优先级高者胜出;层按字母排序,靠后的字母优先级更高(Z > A),可用数字前缀(1.base/2.features/3.admin/)或 extends 数组(第一个条目优先级最高)控制顺序。

当前仓库的测试夹具 test/fixtures/layers-fixture/packages/nuxt/test/layers-fixture/ 正是用于验证层合并、别名与优先级行为的测试工程。

9. content/ 文件式 CMS

content/ 目录由 Nuxt Content 模块启用:模块解析其中的 .md.yml.csv.json 文件,为应用提供文件式 CMS 能力——内置组件渲染内容、MongoDB 风格查询 API、在 Markdown 中以 MDC 语法使用 Vue 组件、自动生成导航(content 文档)。

启用只需一条命令(安装模块并写入 nuxt.config.ts):

npx nuxt module add content

随后把 Markdown 放入 content/(如 content/index.md),并用全捕获路由 + <ContentRenderer> 渲染:

<!-- app/pages/[...slug].vue -->
<script lang="ts" setup>
const route = useRoute()
const { data: page } = await useAsyncData(route.path, () => {
  return queryCollection('content').path(route.path).first()
})
</script>

<template>
  <div>
    <ContentRenderer v-if="page" :value="page" />
  </div>
</template>

10. test/ 测试目录

test/ 是应用测试(单元测试、Nuxt 运行时测试、端到端测试)的推荐位置。Nuxt 不会像扫描 app/server/ 那样扫描它,运行器与布局由你自己决定(通常配合 @nuxt/test-utils)。常见的环境分离布局(test 文档):

-| test/
---| e2e/    # 针对运行中应用的端到端测试
---| nuxt/   # 需要 Nuxt 运行时环境的测试
---| unit/   # 不依赖 Nuxt 运行时的快速 Node 测试

从仓库实践看,test/e2e/test/nuxt/test/fixtures/ 的组织方式正是这一约定的体现:fixture 目录承载各种最小化应用(basicminimalspavapor 等),供测试在隔离环境中启动 Nuxt 并断言行为。

11. 生成目录:.nuxt/.output/

  • .nuxt/文档):开发期由 Nuxt 根据目录结构生成的虚拟文件目录,是理解 Nuxt 生成物(入口、插件、类型等)的最佳学习材料。Nuxt 还为模块提供了虚拟文件系统(VFS),允许模块向该目录添加模板而不落盘,可在开发模式下通过 Nuxt DevTools 的 Virtual Files 页签浏览。整个目录在每次 nuxt dev 时重建,不要手动修改其中文件,并应加入 .gitignore
  • .output/文档):生产构建(nuxt build)的输出目录,即部署产物;同样会在构建时整体重建,应加入 .gitignore

12. 目录结构在仓库源码中的落地

将官方约定与本仓库的实现对照,可以进一步确认各目录机制的来源:

13. 总结:目录职责速查表

路径 职责 关键约定
nuxt.config.ts 应用主配置 存在该文件即项目根;变更触发完整重启
.nuxtrc / .nuxtignore / .env 扁平配置 / 构建忽略 / 环境变量 变更均触发完整重启
app/app.vue 应用根组件 pages/ 时需用 <NuxtPage />
app/pages/ 文件式路由 可选;单根元素;[param][[param]][...slug](group)
app/components/ 自动导入组件 路径决定命名;Lazy.client.serverglobal/
app/composables/app/utils/ 自动导入的 composables 与工具函数 扫描规则同 shared/utils
app/layouts/app/middleware/app/plugins/ 布局 / 前端路由中间件 / 应用插件 自动注册
app/app.config.ts 响应式应用配置 useAppConfig() 访问;勿放密钥
app/error.vue 全局错误页 接收 error: NuxtError prop
public/ 原样按根路径分发的静态文件 不经过构建
`server/api routes middleware
shared/ 应用与服务端共享代码 v3.14+;shared/utilsshared/types 双端自动导入;#shared 别名
modules/ 本地模块 modules/*.tsmodules/*/index.ts 自动注册,字母序执行
layers/ 可复用层 v3.12+ 自动注册;每层必须有 nuxt.config.ts#layers/[name] 别名(v3.16+)
content/ 文件式 CMS 需 Nuxt Content 模块;.md/.yml/.csv/.json
test/ 应用测试 不被 Nuxt 扫描,自行组织 unit/nuxt/e2e
.nuxt/ / .output/ 开发生成目录 / 生产构建产物 均加入 .gitignore,勿手动修改

掌握这套“目录即约定”的体系后,你就可以用最小的心智负担组织一个 Nuxt 全栈应用:把文件放进正确的目录,自动导入、路由、API 端点与模块注册都会由框架代为完成,而你只需在需要突破默认行为时(自定义 components 目录、ignore 规则、层优先级、模块顺序)再回到 nuxt.config 中显式声明。

登录后查看全文
热门项目推荐
相关项目推荐