---
title: "编写 Nuxt 层"
description: "Nuxt 提供了一个强大的系统，允许你扩展默认文件、配置等更多内容。"
canonical_url: "https://nuxt.zhcndoc.com/docs/3.x/guide/going-further/layers"
---
# 编写 Nuxt 层

> Nuxt 提供了一个强大的系统，允许你扩展默认文件、配置等更多内容。

Nuxt 层是一个强大的功能，可以让你在 monorepo 内部，或者从 git 仓库或 npm 包中共享和重用部分 Nuxt 应用。层的结构几乎与标准的 Nuxt 应用相同，使其易于编写和维护。

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/getting-started/layers"}
::

最小的 Nuxt 层目录应包含一个 [`nuxt.config.ts`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/nuxt-config) 文件，以表明它是一个层。

```ts [base/nuxt.config.ts]
export default defineNuxtConfig({})
```

此外，层目录中的某些其他文件将会被 Nuxt 自动扫描，并用于扩展此层的项目。

- [`components/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/components)   - 扩展默认组件
- [`composables/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/composables)  - 扩展默认组合函数
- [`layouts/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/layouts)  - 扩展默认布局
- [`middleware/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/middleware)  - 扩展默认中间件
- [`pages/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/pages)        - 扩展默认页面
- [`plugins/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/plugins)        - 扩展默认插件
- [`utils/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/utils)   - 扩展默认工具函数
- [`app.config.ts`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/app-config)  - 扩展默认应用配置
- [`server/*`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/server)       - 扩展默认服务器端点和中间件
- [`nuxt.config.ts`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/nuxt-config)- 扩展默认 Nuxt 配置

## 基本示例

::code-tree{defaultValue="nuxt.config.ts" expandAll}
```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    './base',
  ],
})
```

```vue [app.vue]
<template>
  <BaseComponent />
</template>
```

```ts [base/nuxt.config.ts]
export default defineNuxtConfig({
  // 继承自 base nuxt.config.ts！
  app: {
    head: {
      title: '扩展配置很有趣！',
      meta: [
        { name: 'description', content: '我正在使用 Nuxt 的 extends 功能！' }
      ],
    }
  }
})
```

```vue [base/components/BaseComponent.vue]
<template>
  <h1>扩展组件很有趣！</h1>
</template>
```
::

## 层优先级

当从多个层扩展时，理解覆盖顺序非常重要。定义相同文件或组件时，**优先级较高**的层会覆盖优先级较低的层。

优先级从高到低为：

1. **你的项目文件** - 始终拥有最高优先级
2. 来自 `~~/layers` 目录的自动扫描层 - 按字母顺序排序（Z 的优先级比 A 高）
3. 配置中的 `extends` 层 - 第一项优先级高于第二项

### 何时使用哪种方式

- **`extends`** - 用于外部依赖（npm 包、远程仓库）或项目目录外的层
- **`~~/layers` 目录** - 用于项目内部的本地层

::tip
如果你需要控制自动扫描层的顺序，可以为它们添加数字前缀：`~/layers/1.z-layer`，`~/layers/2.a-layer`。这样 `2.a-layer` 的优先级会高于 `1.z-layer`。
::

### 示例

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    // 项目外部的本地层
    '../base',
    // NPM 包
    '@my-themes/awesome',
    // 远程仓库
    'github:my-themes/awesome#v1',
  ],
})
```

如果你同时有 `~~/layers/custom`，优先级顺序为：

- 你的项目文件（最高）
- `~~/layers/custom`
- `../base`
- `@my-themes/awesome`
- `github:my-themes/awesome#v1`（最低）

这意味着你的项目文件会覆盖任何层，`~~/layers/custom` 会覆盖 `extends` 中的任何内容。

## 起始模板

要开始使用，你可以通过 [nuxt/starter/layer 模板](https://github.com/nuxt/starter/tree/layer) 初始化一个层。这将创建一个基本结构供你构建。打开终端执行以下命令开始：

```bash [Terminal]
npm create nuxt -- --template layer nuxt-layer
```

接着按照 README 中的说明执行下一步操作。

## 发布层

你可以通过远程资源或 npm 包来发布和分享层。

### Git 仓库

你可以使用 git 仓库来共享你的 Nuxt 层。示例如下：

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    'github:username/repoName',        // GitHub 远程源
    'github:username/repoName/base',   // GitHub 远程源中的 /base 目录
    'github:username/repoName#dev',    // 来自 dev 分支的 GitHub 远程源
    'github:username/repoName#v1.0.0', // 来自 v1.0.0 标签的 GitHub 远程源
    'gitlab:username/repoName',        // GitLab 远程源示例
    'bitbucket:username/repoName',     // Bitbucket 远程源示例
  ],
})
```

::tip
如果你想扩展私有远程源，需要添加环境变量 `GIGET_AUTH=<token>` 来提供访问令牌。
::

::tip
如果你想从自托管的 GitHub 或 GitLab 实例扩展远程源，需要使用环境变量 `GIGET_GITHUB_URL=<url>` 或 `GIGET_GITLAB_URL=<url>` 提供其 URL，或者在你的 `nuxt.config` 中直接配置 [auth 选项](https://github.com/unjs/c12#extending-config-layer-from-remote-sources)。
::

::warning
请注意，如果你将远程源作为层进行扩展，无法在 Nuxt 之外访问其依赖。例如，如果远程层依赖于 eslint 插件，则无法在你的 eslint 配置中使用该插件。这是因为这些依赖项位于一个特殊位置（`node_modules/.c12/layer_name/node_modules/`），你的包管理器无法访问。
::

::note
使用 git 远程源时，如果层含有 npm 依赖且你希望安装它们，可以在层选项中设置 `install: true`。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    ['github:username/repoName', { install: true }],
  ],
})
```
::

### npm 包

你可以将 Nuxt 层作为一个包含你想扩展的文件和依赖的 npm 包发布。这样可以与你人共享配置，在多个项目中使用，或私人使用。

要从 npm 包扩展，需要确保该模块已经发布至 npm 并作为 devDependency 安装在用户项目中。然后你就可以使用模块名称来扩展当前的 Nuxt 配置：

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    // 带作用域的模块
    '@scope/moduleName',
    // 或者仅模块名称
    'moduleName',
  ],
})
```

要将层目录作为 npm 包发布，你需要确保 `package.json` 中正确填写了属性，确保发布时文件被包含。

```json [package.json]
{
  "name": "my-theme",
  "version": "1.0.0",
  "type": "module",
  "main": "./nuxt.config.ts",
  "dependencies": {},
  "devDependencies": {
    "nuxt": "^3.0.0"
  }
}
```

::important
确保层中导入的所有依赖都**显式添加**到 `dependencies` 中。`nuxt` 依赖和仅用于发布前测试层的依赖，应保留在 `devDependencies` 字段。
::

现在你可以继续将模块发布到 npm，无论是公开还是私有。

::important
将层作为私有 npm 包发布时，确保你已登录，以便通过 npm 认证下载该模块。
::

## 小技巧

### 命名层别名

自动扫描的层（来自你的 `~~/layers` 目录）会自动创建别名。例如，你可以通过 `#layers/test` 访问你的 `~~/layers/test` 层。

如果你想为其他层创建命名别名，可以在层配置中指定名称：

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  $meta: {
    name: 'example',
  },
})
```

这将生成一个别名 `#layers/example` 指向你的层。

### 相对路径与别名

在层的组件和组合函数中使用全局别名（如 `~/` 和 `@/`）进行导入时，注意这些别名是相对于用户项目路径解析的。作为解决方法，你可以**使用相对路径**导入，或者使用命名层别名。

此外，在层的 `nuxt.config` 文件中使用相对路径时（嵌套 `extends` 除外），它们是相对于用户项目解析的，而不是层本身。作为解决方法，在 `nuxt.config` 中使用完整的解析路径：

```ts [nuxt.config.ts]
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'

const currentDir = dirname(fileURLToPath(import.meta.url))

export default defineNuxtConfig({
  css: [
    join(currentDir, './assets/main.css'),
  ],
})
```

## 禁用层中的模块

当扩展一个层时，你可能想禁用该层包含的某些模块。你可以在 Nuxt 配置中将模块的配置键设置为 `false` 来实现。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: ['./base-layer'],
  // 通过将模块配置键设为 false 来禁用层中的模块
  image: false, // 禁用 @nuxt/image
  pinia: false, // 禁用 @pinia/nuxt
})
```

::note
配置键由各模块定义。常见示例如 `image` 对应 `@nuxt/image`，`pinia` 对应 `@pinia/nuxt`，`content` 对应 `@nuxt/content`。请查看各模块文档获取具体配置键。
::

此功能适用于：

- 层包含你项目不需要的模块
- 你想使用与层不同的实现
- 你需要在特定环境中禁用分析或其他模块

::tip
你也可以用此方法禁用你自己项目中的模块，而不仅仅是层中的。将模块配置键设为 `false` 会阻止其 setup 函数运行，同时仍会生成模块的类型。
::

## 支持多层的 Nuxt 模块

你可以使用 Nuxt Kit 中的 [`getLayerDirectories`](https://nuxt.zhcndoc.com/docs/3.x/api/kit/layers#getlayerdirectories) 工具，为你的模块提供自定义的多层处理支持。

```ts [modules/my-module.ts]
import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'

export default defineNuxtModule({
  setup (_options, nuxt) {
    const layerDirs = getLayerDirectories()

    for (const [index, layer] of layerDirs.entries()) {
      console.log(`Layer ${index}:`)
      console.log(`  Root: ${layer.root}`)
      console.log(`  App: ${layer.app}`)
      console.log(`  Server: ${layer.server}`)
      console.log(`  Pages: ${layer.appPages}`)
      // ... 其他目录
    }
  },
})
```

**注意事项：**

- 数组中靠前的项优先级更高，会覆盖后面的项
- 用户的项目位于数组的第一项

## 深入探究

配置加载和 extends 支持由 [unjs/c12](https://github.com/unjs/c12) 负责，合并使用 [unjs/defu](https://github.com/unjs/defu)，远程 git 源支持使用了 [unjs/giget](https://github.com/unjs/giget)。查看文档和源代码以了解更多信息。

::read-more{icon="i-simple-icons-github" to="https://github.com/nuxt/nuxt/issues/13367" target="_blank"}
查看我们在 GitHub 上针对层支持进行的持续开发和改进。
::


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
