Skip to content

创建层

最小层结构

text
my-layer/
└── nuxt.config.ts    # 必须存在,标识这是一个层
ts
// my-layer/nuxt.config.ts
export default defineNuxtConfig({})

为什么 nuxt.config.ts 必须存在?

Nuxt 通过它识别一个目录是否为层。没有这个文件,Nuxt 不会把目录当作层处理。

完整层结构

text
my-layer/
├── nuxt.config.ts         # 层配置
├── app/
│   ├── assets/            # 样式和资源
│   ├── components/        # 组件
│   ├── composables/       # 组合式函数
│   ├── layouts/           # 布局
│   ├── middleware/        # 中间件
│   ├── pages/             # 页面
│   ├── plugins/           # 插件
│   └── utils/             # 工具函数
├── server/
│   ├── api/               # API 路由
│   ├── middleware/         # 服务端中间件
│   ├── plugins/            # 服务端插件
│   └── utils/              # 服务端工具
└── shared/                # 共享代码

层配置

ts
// my-layer/nuxt.config.ts
export default defineNuxtConfig({
  // 层的元信息
  $meta: {
    name: 'my-layer',  // 命名别名,生成 #layers/my-layer 别名
  },

  // 层提供的模块
  modules: [
    '@nuxt/ui',
    '@pinia/nuxt',
  ],

  // 层提供的配置
  app: {
    head: {
      titleTemplate: '%s - My Layer',
    },
  },

  // 层提供的运行时配置
  runtimeConfig: {
    public: {
      layerVersion: '1.0.0',
    },
  },

  // 层提供的 CSS
  css: ['~/app/assets/css/layer.css'],
})

INFO

css 中的 ~ 指向项目根 不是层本身。 如果 CSS 文件在层中,应该使用 createResolver 解析路径(见下方注意事项)

带命名别名的层

ts
// 层的 nuxt.config.ts
export default defineNuxtConfig({
  $meta: {
    name: 'admin',
  },
})

设置 name 后,可以通过 #layers/admin 别名引用层中的文件:

ts
// 在项目中导入层中的特定文件
import { AdminLayout } from '#layers/admin/app/layouts/AdminLayout.vue'

什么时候需要命名别名?

当项目中需要显式引用层中的某个文件(而非依赖自动导入)时使用。大多数情况下,层的组件、组合式函数会自动注册,不需要手动导入。

层中的组件

text
my-layer/
└── app/
    └── components/
        ├── BaseButton.vue    → <BaseButton>
        └── AdminSidebar.vue  → <AdminSidebar>

使用层的项目自动获得这些组件,无需手动 import

层中的页面

text
my-layer/
└── app/
    └── pages/
        └── admin/
            ├── index.vue     → /admin
            └── users.vue     → /admin/users

项目可以覆盖层中的页面:

text
my-app/
└── app/
    └── pages/
        └── admin/
            └── users.vue     # 覆盖层中的 users.vue

覆盖机制的理解

同路径的文件,项目自身的版本优先于层中的版本。这不是"修改"层文件,而是"替换"——层文件不变,只是项目提供了自己的实现。

创建层模板

使用官方模板快速创建:

bash
npx nuxi init -t layer my-layer

注意事项

1. 层的 nuxt.config.ts 必须存在

这是层的标识。没有它,Nuxt 不识别该目录为层。即使为空也要创建。

2. 路径别名指向项目根

这是创建层时最容易犯的错误

层中的 ~@ 别名解析到使用层的项目根目录,不是层本身。这是因为层的代码会被"注入"到项目的上下文中执行,而非独立运行。

ts
// ❌ 错误:~ 指向项目根,不是层根
css: ['~/app/assets/css/layer.css']  // 可能解析到项目的 CSS,不是层的

// ✅ 正确:使用 createResolver 解析层的路径
import { createResolver } from '@nuxt/kit'
const { resolve } = createResolver(import.meta.url)

export default defineNuxtConfig({
  css: [resolve('./app/assets/css/layer.css')],  // 始终指向层中的文件
})

经验法则

层的 nuxt.config.ts 中凡是涉及文件路径的配置,都应该使用 createResolver,而不是 ~/@ 别名。

3. 运行时 vs 构建时

层的 nuxt.config.ts 在构建时执行,app/server/ 下的代码在运行时执行。不要在 nuxt.config.ts 中使用运行时 API(如 useStateuseRouter)。

4. 依赖声明

层中使用的依赖需要声明在层的 package.json 中。否则,使用层的项目可能缺少依赖而报错。

json
// my-layer/package.json
{
  "name": "my-layer",
  "dependencies": {
    "@nuxt/ui": "^3.0.0"
  }
}

常见问题

问题原因解决方案
层不被识别缺少 nuxt.config.ts在层根目录创建 nuxt.config.ts
CSS 加载的是项目文件而非层文件~ 指向项目根使用 createResolver 解析路径
层的组件没有自动注册组件目录不在 app/components/确保组件路径正确
层的依赖缺失没有在层的 package.json 中声明在层的 package.json 中添加依赖
runtimeConfig 中的配置被项目覆盖项目配置优先级高于层在项目中不声明同名配置,或在项目中显式设置

基于 Nuxt 4 官方文档整理编写