层简介
为什么需要层?
想象你在开发多个 Nuxt 项目(公司官网、管理后台、客户门户),它们共享相同的导航栏、布局、主题配置和工具函数。不用层,你需要手动复制这些文件到每个项目,改一处就要改多处——维护成本极高。层让你定义一次,到处复用,子项目还能按需覆盖。
什么是层?
层(Layer)是一个拥有 nuxt.config.ts 的 Nuxt 项目片段,可以被其他项目继承。类似于"模板"或"主题"的概念。
与模块不同,层不仅可以提供功能,还能提供完整的页面、布局、组件等 UI 资源,并且子项目可以覆盖层中的任何文件。
层能做什么?
| 能力 | 说明 |
|---|---|
| 共享页面 | 多个项目共用相同的页面 |
| 共享布局 | 统一的布局模板 |
| 共享组件 | 通用组件库 |
| 共享组合式函数 | 公共业务逻辑 |
| 共享服务端逻辑 | API 路由、中间件 |
| 共享配置 | 统一的构建和运行时配置 |
| 文件覆盖 | 子项目可以覆盖层中的任何文件 |
使用场景
| 场景 | 说明 |
|---|---|
| 主题系统 | 多个项目共用 UI 主题(颜色、字体、布局) |
| Monorepo | 多个应用共享组件和逻辑 |
| SaaS 产品 | 基础功能 + 客户定制层 |
| 内部工具 | 公司统一的组件库和规范 |
| 多租户 | 核心层 + 租户特定层 |
| 开源主题 | 发布可复用的 Nuxt 主题 |
层与模块的区别
| 特性 | Layer | Module |
|---|---|---|
| 代码共享 | 组件、页面、布局 | 功能、插件、组合式函数 |
| 配置继承 | ✅ 完整继承 nuxt.config | ❌ 仅配置项 |
| 文件覆盖 | ✅ 子项目可覆盖层文件 | ❌ 不支持覆盖 |
| UI 资源 | ✅ 页面、布局、样式 | ❌ 通常不提供 |
| 安装方式 | extends 或 layers/ 目录 | modules 数组 |
| 适用场景 | UI 和结构复用 | 功能扩展 |
| 发布方式 | npm 包或 Git 仓库 | npm 包 |
TIP
简单记法:模块提供功能 层提供结构。如果需要共享 UI 模板,用层;如果需要集成第三方服务,用模块
它们可以一起用
层中可以声明模块依赖,模块也可以引用层。比如一个"管理后台层"可能依赖 @nuxt/ui 模块。
两种使用方式
1. layers/ 目录(自动注册)
text
my-app/
├── layers/
│ └── admin/
│ ├── nuxt.config.ts # 必须存在(即使为空)
│ ├── app/
│ │ ├── pages/ # 管理后台页面
│ │ ├── components/ # 管理后台组件
│ │ └── layouts/ # 管理后台布局
│ └── server/
│ └── api/ # 管理后台 API
└── nuxt.config.tslayers/ 目录下的层会被自动注册,无需手动配置。
TIP
层目录名就是层名 如 layers/admin/ 的层名为 admin
2. extends 配置
ts
// nuxt.config.ts
export default defineNuxtConfig({
extends: [
'../shared-layer', // 本地路径
'@myorg/nuxt-layer', // npm 包
'github:myorg/nuxt-layer#v1.0.0', // GitHub 仓库
],
})| 来源 | 语法 | 说明 |
|---|---|---|
| 本地路径 | '../shared' | 相对路径,开发方便 |
| npm 包 | '@myorg/layer' | 发布到 npm 的层 |
| GitHub | 'github:user/repo#branch' | 直接从 Git 引用 |
两种方式的选择
项目内的层用 layers/ 目录(简单、自动注册),跨项目共享的层用 extends(更灵活、支持远程)。
层的优先级
从高到低:
- 项目自身文件(最高优先级)— 总是优先于层中的同名文件
layers/目录中的层 — 按字母排序,Z > Aextends中的层 — 第一个 > 最后一个
ts
// 示例:admin 层的组件可覆盖 base 层的同名组件
export default defineNuxtConfig({
extends: [
'../base-layer', // 优先级低
'../admin-layer', // 优先级高(可覆盖 base)
],
})为什么这样设计?
项目自身文件优先 = 你始终拥有最终控制权。后声明的层优先 = 后面的层可以"定制"前面的层。这遵循了"控制反转"原则——基础层提供默认实现,项目按需覆盖。
完整示例:同文件覆盖
bash
# 层中的文件
base-layer/app/pages/about.vue → 层版本
# 项目中的文件(优先使用)
my-app/app/pages/about.vue → 项目版本访问 /about 时,使用的是项目中的 about.vue,层中的版本被覆盖。
常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 层不生效 | 忘记创建 nuxt.config.ts | 层根目录必须有 nuxt.config.ts,即使为空 |
| 层的组件没被自动注册 | 组件目录结构不对 | 确保组件在 app/components/ 下 |
| 多层覆盖同一文件 | 不确定最终使用哪个 | 用 nuxt info 查看层的加载顺序 |
layers/ 中层的优先级不符预期 | 按字母排序,不是按需要 | 用数字前缀控制顺序(1.base、2.theme) |