编写 Nuxt 层

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

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

Read more in Docs > Getting Started > Layers.

一个最小的 Nuxt 层目录应该包含一个 nuxt.config.ts 文件,用以标明这是一个层。

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

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

基本示例

export default defineNuxtConfig({
  extends: [
    './base'
  ]
})

起始模板

要开始使用,你可以通过 nuxt/starter/layer 模板 初始化一个层。这将创建一个基本结构供你构建。打开终端执行以下命令开始:

Terminal
npm create nuxt -- --template layer nuxt-layer

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

发布层

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

Git 仓库

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

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 远程源示例
  ]
})
如果你想扩展私有远程源,需要添加环境变量 GIGET_AUTH=<token> 来提供访问令牌。
如果你想从自托管的 GitHub 或 GitLab 实例扩展远程源,需要使用环境变量 GIGET_GITHUB_URL=<url>GIGET_GITLAB_URL=<url> 提供其 URL,或者在你的 nuxt.config 中直接配置 auth 选项
请注意,如果你将远程源作为层进行扩展,无法在 Nuxt 之外访问其依赖。例如,如果远程层依赖于 eslint 插件,则无法在你的 eslint 配置中使用该插件。这是因为这些依赖项位于一个特殊位置(node_modules/.c12/layer_name/node_modules/),你的包管理器无法访问。
使用 git 远程源时,如果层含有 npm 依赖且你希望安装它们,可以在层选项中设置 install: true
nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    ['github:username/repoName', { install: true }]
  ]
})

npm 包

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

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

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

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

package.json
{
  "name": "my-theme",
  "version": "1.0.0",
  "type": "module",
  "main": "./nuxt.config.ts",
  "dependencies": {},
  "devDependencies": {
    "nuxt": "^3.0.0"
  }
}
确保层中导入的所有依赖都显式添加dependencies 中。nuxt 依赖和仅用于发布前测试层的依赖,应保留在 devDependencies 字段。

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

将层作为私有 npm 包发布时,确保你已登录,以便与 npm 认证下载该模块。

小技巧

命名层别名

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

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

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

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

相对路径与别名

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

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

nuxt.config.ts
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'

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

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

多层支持的 Nuxt 模块

你可以使用内部数组 nuxt.options._layers,为你的模块支持自定义多层处理。

modules/my-module.ts
export default defineNuxtModule({
  setup(_options, nuxt) {
    for (const layer of nuxt.options._layers) {
      // 你可以检测每个层的自定义目录是否存在以扩展
      console.log('针对层的自定义扩展', layer.cwd, layer.config)
    }
  }
})

注意事项:

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

深入探究

配置加载和 extends 支持由 unjs/c12 负责,合并使用 unjs/defu,远程 git 源支持使用了 unjs/giget。查看文档和源代码以了解更多信息。

查看我们在 GitHub 上针对层支持进行的持续开发和改进。