创建层
最小层结构
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(如 useState、useRouter)。
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 中的配置被项目覆盖 | 项目配置优先级高于层 | 在项目中不声明同名配置,或在项目中显式设置 |