编写 Nuxt 层

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

Nuxt 模块是一项强大的功能,可用于在 monorepo 中、从 git 仓库或 npm 包中共享和重用部分的 Nuxt 应用程序。模块的结构与标准 Nuxt 应用程序几乎相同,这使得它们易于编写和维护。

文档 > 4 X > 入门 > 模块 中阅读更多内容。

一个最小的 Nuxt 模块目录应包含一个 nuxt.config.ts 文件,以指示它是一个模块。

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

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

基本示例

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

模块优先级

当从多个模块扩展时,了解覆盖顺序很重要。具有更高优先级的模块会覆盖优先级较低的模块,如果它们定义了相同的文件或组件。

优先级顺序(从高到低)是

  1. 您的项目文件 - 始终具有最高优先级
  2. 来自 ~~/layers 目录的自动扫描模块 - 按字母顺序排序(Z 的优先级高于 A)
  3. extends 配置中的模块 - 第一个条目的优先级高于第二个

何时使用

  • extends - 用于外部依赖项(npm 包、远程仓库)或项目目录之外的模块
  • ~~/layers 目录 - 用于作为项目一部分的本地模块
如果您需要控制自动扫描模块的顺序,可以通过数字前缀来指定它们:~/layers/1.z-layer, ~/layers/2.a-layer。这样 2.a-layer 的优先级将高于 1.z-layer

示例

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    // Local layer outside the project
    '../base',
    // NPM package
    '@my-themes/awesome',
    // Remote repository
    'github:my-themes/awesome#v1',
  ],
})

如果您还有 ~~/layers/custom,优先级顺序是

  • 您的项目文件(最高)
  • ~~/layers/custom
  • ../base
  • @my-themes/awesome
  • github:my-themes/awesome#v1 (最低)

这意味着您的项目文件将覆盖任何模块,而 ~~/layers/custom 将覆盖 extends 中的任何内容。

启动模板

要开始,您可以使用nuxt/starter/layer 模板来初始化一个模块。这将创建一个您可以基于其进行构建的基本结构。在终端中执行此命令即可开始

终端
npm create nuxt -- --template layer nuxt-layer

请遵循 README 中的说明进行后续步骤。

发布模块

您可以通过使用远程源或 npm 包来发布和共享模块。

Git 仓库

您可以使用 git 仓库来共享您的 Nuxt 模块。一些示例

nuxt.config.ts
export default defineNuxtConfig({
  extends: [
    // GitHub Remote Source
    'github:username/repoName',
    // GitHub Remote Source within /base directory
    'github:username/repoName/base',
    // GitHub Remote Source from dev branch
    'github:username/repoName#dev',
    // GitHub Remote Source from v1.0.0 tag
    'github:username/repoName#v1.0.0',
    // GitLab Remote Source example
    'gitlab:username/repoName',
    // Bitbucket Remote Source example
    'bitbucket:username/repoName',
  ],
})
如果您想扩展私有远程源,您需要在其中添加环境变量 GIGET_AUTH=<token> 以提供一个令牌。
如果您想从自托管的 GitHub 或 GitLab 实例扩展远程源,您需要使用 GIGET_GITHUB_URL=<url>GIGET_GITLAB_URL=<url> 环境变量来提供其 URL - 或者直接使用您的 auth 选项在您的nuxt.config 中进行配置。
请记住,如果您将远程源作为模块扩展,您将无法在 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: [
    // Node Module with scope
    '@scope/moduleName',
    // or just the module name
    '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 进行身份验证以下载 node 模块。

提示

命名模块别名

自动扫描的模块(来自您的 ~~/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 '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'),
  ],
})

禁用模块中的模块

扩展模块时,您可能希望禁用它包含的某些模块。您可以通过在 Nuxt 配置中将模块的配置键设置为 false 来实现。

nuxt.config.ts
export default defineNuxtConfig({
  extends: ['./base-layer'],
  // Disable modules from the layer by setting their config key to false
  image: false, // Disables @nuxt/image
  pinia: false, // Disables @pinia/nuxt
})
配置键由每个模块定义。常见示例包括 image (对于 @nuxt/image), pinia (对于 @pinia/nuxt), 和 content (对于 @nuxt/content)。请查阅模块文档以了解其特定的配置键。

这在以下情况下很有用

  • 模块包含您项目中不需要的模块
  • 您想使用与模块提供的实现不同的实现
  • 您需要在特定环境中禁用分析或其他模块
您也可以使用此方法来禁用您自己项目中的模块 - 不仅仅是来自模块的模块。将模块的配置键设置为 false 将阻止其设置函数运行,同时仍为模块生成类型。

Nuxt 模块的多模块支持

您可以使用 Nuxt Kit 中的 getLayerDirectories 工具来为您的模块支持自定义的多模块处理。

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}`)
      // ... other directories
    }
  },
})

注意事项

  • 数组中较早的项具有更高的优先级并覆盖后面的项
  • 用户的项目是数组中的第一项

深入了解

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

在 GitHub 上查看我们正在进行的开发,以带来更多关于模块支持的改进。