编写你自己的 Yeoman 生成器

生成器是 Yeoman 生态系统的构建块。它们是由 yo 运行的插件,用于为最终用户生成文件。

阅读本节内容,您将了解如何创建和分发自己的生成器。

组织你的生成器

设置为 Node 模块

从本质上讲,生成器是一个 Node.js 模块。

首先,创建一个文件夹,您将在其中编写生成器。此文件夹必须命名为 generator-name(其中 name 是生成器的名称)。这一点很重要,因为 Yeoman 依赖于文件系统来查找可用的生成器。

在生成器文件夹内,创建一个 package.json 文件。此文件是 Node.js 模块清单。您可以通过在命令行中运行 npm init 或手动输入以下内容来生成此文件。

{
  "name": "generator-name",
  "version": "0.1.0",
  "description": "",
  "files": [
    "generators"
  ],
  "keywords": ["yeoman-generator"],
  "dependencies": {
    "yeoman-generator": "^1.0.0"
  }
}

name 属性必须以 generator- 为前缀。 keywords 属性必须包含 "yeoman-generator",并且存储库必须具有描述才能被我们的 生成器页面 索引。

您应该确保将最新版本的 yeoman-generator 设置为依赖项。您可以通过运行以下命令来实现:npm install --save yeoman-generator

files 属性必须是您的生成器使用的文件和目录的数组。

根据需要添加其他 package.json 属性

文件夹树

Yeoman 的功能取决于您如何构建目录树。每个子生成器都包含在自己的文件夹中。

当您调用 yo name 时使用的默认生成器是 app 生成器。它必须包含在 app/ 目录中。

子生成器(当您调用 yo name:subcommand 时使用)存储在与子命令完全相同的名称的文件夹中。

在一个示例项目中,目录树可能如下所示

├───package.json
└───generators/
    ├───app/
    │   └───index.js
    └───router/
        └───index.js

此生成器将公开 yo nameyo name:router 命令。

Yeoman 允许两种不同的目录结构。它将在 ./generators/ 中查找以注册可用的生成器。

前面的示例也可以写成如下形式

├───package.json
├───app/
│   └───index.js
└───router/
    └───index.js

如果您使用此第二种目录结构,请确保将 package.json 中的 files 属性指向所有生成器文件夹。

{
  "files": [
    "app",
    "router"
  ]
}

扩展生成器

一旦您有了这个结构,就可以编写实际的生成器了。

Yeoman 提供了一个基本生成器,您可以扩展它来实现自己的行为。此基本生成器将添加您期望的大多数功能以简化您的任务。

在生成器的 index.js 文件中,以下是您扩展基本生成器的方式

var Generator = require('yeoman-generator');

module.exports = class extends Generator {};

我们将扩展的生成器分配给 module.exports 以使其可用于生态系统。这就是我们在 Node.js 中 导出模块 的方式。

覆盖构造函数

某些生成器方法只能在 constructor 函数内部调用。这些特殊方法可能会执行诸如设置重要状态控件等操作,并且可能无法在构造函数之外运行。

要覆盖生成器构造函数,请添加一个构造函数方法,如下所示

module.exports = class extends Generator {
  // The name `constructor` is important here
  constructor(args, opts) {
    // Calling the super constructor is important so our generator is correctly set up
    super(args, opts);

    // Next, add your custom code
    this.option('babel'); // This method adds support for a `--babel` flag
  }
};

添加你自己的功能

添加到原型中的每个方法都会在调用生成器后运行,通常按顺序运行。但是,正如我们将在下一节中看到的,某些特殊方法名称将触发特定的运行顺序。

让我们添加一些方法

module.exports = class extends Generator {
  method1() {
    this.log('method 1 just ran');
  }

  method2() {
    this.log('method 2 just ran');
  }
};

当我们稍后运行生成器时,您将看到这些行记录到控制台中。

运行生成器

此时,您拥有一个可工作的生成器。下一个合乎逻辑的步骤是运行它并查看它是否有效。

由于您正在本地开发生成器,因此它尚未作为全局 npm 模块可用。可以使用 npm 创建全局模块并将其符号链接到本地模块。以下是要执行的操作

在命令行中,从生成器项目的根目录(在 generator-name/ 文件夹中)键入

npm link

这将安装项目的依赖项并将全局模块符号链接到您的本地文件。npm 完成后,您将能够调用 yo name,并且您应该会看到前面定义的 this.log 渲染在终端中。恭喜,您刚刚构建了您的第一个生成器!

查找项目根目录

在运行生成器时,Yeoman 将尝试根据其运行的文件夹上下文来确定一些信息。

最重要的是,Yeoman 在目录树中搜索 .yo-rc.json 文件。如果找到,则将文件的位置视为项目的根目录。在后台,Yeoman 将将当前目录更改为 .yo-rc.json 文件位置并在那里运行请求的生成器。

Storage 模块创建 .yo-rc.json 文件。第一次从生成器中调用 this.config.save() 将创建该文件。

因此,如果您的生成器未在您的当前工作目录中运行,请确保您的目录树中没有 .yo-rc.json

接下来去哪里?

阅读完本文后,您应该能够创建本地生成器并运行它。

如果这是您第一次编写生成器,则绝对应该阅读下一节关于 运行上下文和运行循环 的内容。本节对于理解生成器将运行的上下文以及确保它能够与 Yeoman 生态系统中的其他生成器很好地组合至关重要。文档的其他部分将介绍 Yeoman 核心提供的功能,以帮助您实现目标。