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

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

Nuxt 层（layers）是一个强大的特性，允许你在 monorepo 中或从 git 仓库或 npm 包中共享和重用部分 Nuxt 应用。层的结构与标准的 Nuxt 应用几乎相同，这使得它们易于编写和维护。

<read-more to="https://nuxt.zhcndoc.com/docs/4.x/getting-started/layers">



</read-more>

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

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

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

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

## 基本示例

<code-tree :expand-all="true" default-value="nuxt.config.ts">

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

```vue [app/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/app/components/BaseComponent.vue]
<template>
  <h1>扩展组件很有趣！</h1>
</template>
```

</code-tree>

## 层优先级

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

优先级从高到低依次为：

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`。

</tip>

### 例子

```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 远程源
    'github:username/repoName',
    // GitHub 远程源 /base 目录
    'github:username/repoName/base',
    // GitHub dev 分支
    'github:username/repoName#dev',
    // GitHub v1.0.0 标签
    'github:username/repoName#v1.0.0',
    // GitLab 远程源示例
    'gitlab:username/repoName',
    // Bitbucket 远程源示例
    'bitbucket:username/repoName',
  ],
})
```

<note>

我们建议将你的层内容作为 npm 包发布（公开或私有，例如通过 [GitHub Packages](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages)），而不是依赖远程层。

或者，你也可以直接将一个 [远程 git URL 作为依赖项](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#git-urls-as-dependencies) 添加。

</note>

<tip>

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

</tip>

<tip>

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

</tip>

<warning>

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

</warning>

<note>

使用 git 远程源时，如果某个层具有 npm 依赖且你希望安装它们，可以在层选项中通过指定 `install: true` 来实现。

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

</note>

### npm 包

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

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

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  extends: [
    // 带作用域的 Node 模块
    '@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` 字段中。

</important>

现在你可以继续将模块发布到 npm，公开或私有均可。

<important>

将层作为私有 npm 包发布时，需要确保你已登录，以便进行 npm 认证来下载该 node 模块。

</important>

## 提示

### 命名层别名

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

如果你想为其他层创建命名别名，可以在该层的配置中指定一个名称。

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

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

### 相对路径与别名

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

另外，在层的 `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, './app/assets/main.css'),
  ],
})
```

## 从层中禁用模块 <badge className="align-middle" color="info" size="xs">v4.3</badge>

当扩展一个层时，你可能希望禁用其中包含的某些模块。你可以通过在你的 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`）。具体请查阅相应模块的文档以获取其配置键名称。

</note>

这种做法特别适用于：

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

<tip>

你也可以使用此方法在你自己的项目中禁用模块，而不仅限于层中的模块。将某个模块的配置键设为 `false` 将阻止该模块的 setup 函数运行，但仍然会生成该模块的类型。

</tip>

## Nuxt 模块的多层支持

你可以使用 Nuxt Kit 中的 [`getLayerDirectories`](https://nuxt.zhcndoc.com/docs/4.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(`层 ${index}:`)
      console.log(`  根目录: ${layer.root}`)
      console.log(`  应用: ${layer.app}`)
      console.log(`  服务端: ${layer.server}`)
      console.log(`  页面: ${layer.appPages}`)
      // ... 其它目录
    }
  },
})
```

**注意：**

- 数组中的前面项具有更高的优先级，并覆盖后面的项
- 用户的项目是数组中的第一项

## 深入了解

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

<read-more to="https://github.com/nuxt/nuxt/issues/13367" icon="i-simple-icons-github" target="_blank">

查看我们在 GitHub 上持续进行的关于层支持改进的开发工作。

</read-more>


## Sitemap

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