Yeoman

304 阅读5分钟

Yeoman

The web's scaffolding tool for modern webapps

  • Yeoman 是一个可以帮助开发者快速开启一个新项目的工具集。

  • Yeoman 提出一个 Yeoman 工作流的概念,通过脚手架工具(yo),构建工具(grunt gulp 等)和包管理器(npm bower 等)的配合使用让开发者专注于业务的逻辑。

  • Yeoman 的官网中可以搜索到用于初始化项目的 generator,可以用于快速开启项目。

  • Yeoman 也提供给开发者如何定义自己的 generator,所有我们自己开发的 generator 都作为一个插件可以通过 yo 工具创建出我们需要的结构。

  • Yeoman 的 generator-generator 工具可用于构建自己的 generator,自己创建的 generator 可以是很简单的创建几个模板页面,也可以通过和用户交互构建一套量身定制的项目,取决于项目初始化的策略。

环境支持

  1. 安装 node;

  2. 在全局范围安装 yarn:

npm i -g yarn
  1. 在全局范围安装 yo:
$ npm install yo --global # or yarn global add yo
  1. 安装对应的 generator:
$ npm install generator-node --global # or yarn global add generator-node
  1. 通过 yo 运行 generator
$ cd path/to/project-dir
$ mkdir my-module
$ yo node

Sub Generator

在已有的项目基础上创建一些指定的文件

  • 给已存在的项目创建 README 文件;
  • 在原有项目支持上添加某些类型的配置文件 ESLink 配置文件 / Babel 配置文件;

cli 生成器

cli 生成器是 generator-node 里提供的一个子集生成器,用来生成一个 cli 应用所需要的文件;

  1. 将应用变成 cli 应用:
yo node:cli

Yeoman 使用步骤总结

  1. 明确你的需求;
  2. 找到合适的 Generator;
  3. 全局范围安装找到的 Generator;
  4. 通过 Yo 运行对应的 Generator;
  5. 通过命令行交互填写选项;
  6. 生成你所需要的项目结构;

网页应用的创建

  1. 明确你的需求 —— 使用 Yeoman 创建网页应用
  2. 找到合适的 Generator —— Yeoman 官网找到对应的 Generator(webapp)
  3. 全局范围安装找到的 Generator —— yarn global add generator-webapp
  4. 通过 Yo 运行对应的 Generator —— yo webapp
  5. 通过命令行交互填写选项 —— ...
  6. 生成你所需要的项目结构 —— ...

image.png

自定义 Generator

创建 Generator 模块

Generator 本质上就是一个 NPM 模块

  • Generator 基本结构(app 目录就是默认的生成器目录);

image.png

  • 添加一个新的 Generator 目录(component 目录就是我们添加的子生成器目录);

image.png

  • Yeoman 的 Generator 名称必须是 generator- 的格式;

image.png

  • 最基本的 Yeoman 生成器的开发过程;

    1. 初始化
    mkdir generator-sample  // 创建测试目录
    cd generator-sample\  // 进入测试目录
    yarn init // 在测试目录中创建 package.json 文件
    yarn add yeoman-generator // 在目录中安装 yeoman-generator 模块(该模块提供了一些工具函数,让我们在创建生成器的时候更加便捷)
    code . // 打开测试目录
    // 创建 generators/app/index.js
    
    1. 编写 generators/app/index.js
    // 此文件作为 Generator 的核心入口
    // 需要导出一个继承自 Yeoman Generator 的类型
    // Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
    // 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入
    
    const Generator = require('yeoman-generator')
    
    module.exports = class extends Generator {
        writing() {
            // Yeoman 自动在生成文件阶段调用此方法
            // 我们这里尝试往项目目录中写入文件
            this.fs.write(
                this.destinationPath('temp.txt'),
                Math.random().toString()
            )
        }
    }
    
    1. 使用
    yarn link // 链接我们写的 Generator(生成器)
    mkdir my-proj // 创建使用演示目录
    cd my-proj/ // 进入使用演示目录
    yo sample // 使用我们写的 Generator(生成器)
    

根据模板创建文件

  1. 创建 templates 目录,创建模板文件;

image.png

  1. 编写模板文件;

image.png

  1. 编写生成器 index.js 文件; 通过模板方式写入文件到目标目录,使用 fs.copyTpl() 方法

image.png

总结

  • 相对于手动创建每一个文件,模板的方式大大提高了效率;

接收用户输入数据

prompting 方法:Yeoman 在询问用户环节会自动调用此方法,在此方法中可以调用父类的 prompt() 方法发出对用户的命令行询问, prompt() 方法的返回值是一个 Promise 对象

// 此文件作为 Generator 的核心入口
// 需要导出一个继承自 Yeoman Generator 的模型
// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如:文件写入

const Generator = require('yeoman-generator')

module.exports = class extends Generator {
    promiting() {
        // Yeoman 在询问用户环节会自动调用此方法
        // 在此方法中可以调用父类的 prompt() 方法发出对用户的命令行询问
        // prompt() 方法接收一个数组对象,该数组对象中的每一个元素都是一个问题对象
        return this.prompt([{
            type: 'input',
            name: 'name',
            message: 'Your project name',
            default: this.appname // appname 为父类当中自动为我们生成的当前生成项目中目录的文件夹名字
        }, {
            type: 'confirm',
            name: 'success',
            message: '请问您是否要开启 success 开关?',
            default: false
        }]).then(answers => {
            // answers => { name: 'user input value' }
            this.answers = answers
        })
    }
    writing() {
        // // Yeoman 自动在生成文件阶段调用此方法
        // // 我们这里尝试往项目目录中写入文件
        // this.fs.write(
        //     this.destinationPath('temp.txt'),
        //     Math.random().toString(),
        // )

        // 通过模板方式写入文件到目标目录

        // 1. 模板文件路径
        // this.templatePath 获取当前生成器下 templates 目录中的文件路径
        const tmpl = this.templatePath('bar.html')

        // 2. 输出目标路径
        // this.destinationPath 获取生成项目目录下对应的文件路径
        const output = this.destinationPath('bar.html')

        // 3. 模板数据上下文
        const ctx = this.answers

        this.fs.copyTpl(tmpl, output, ctx)
    }
}

总结

  • Yeoman 当中动态接收用户输入数据的方式:prompting()

发布 Generator

Generator 实际上就是一个 npm 模块。因此,发布一个 Generator 实际上就是发布一个 npm 模块,即通过 npm publish / yarn publish 命令将其发布成一个公共的模块即可。

注意

  • 淘宝镜像为只读镜像,发布时应该使用官方的镜像
yarn publish --registry=https://registry.yarnpkg.com