Yargs

264 阅读4分钟

前端脚手架开发利器之一的 Yargs 的学习笔记。


一 介绍

脚手架开发利器。通过解析参数,注册命令(command)及选项(option),十分便捷的开发自定义的前端脚手架。

npm Yargs github Yargs

二 API

构建一个简单的脚手架测试环境,可以随写随测:

mkdir yarg-learn
cd yarg-learn
npm init -y
npm install yargs --save

// package.json 中配置 bin 属性
"bin": {
    "yargs-learn": "/bin/index.js"
}

/**
* /bin/index.js 中写入如下代码
* 配置 api 后,运行 yargs-learn --help 可查看相应的帮助信息
* 或者在代码里 console.log() 想看的信息
*/
#!/usr/bin/env node
const yargs = require("yargs/yargs");
const { hideBin } = require("yargs/helpers");
const arg = hideBin(process.argv);

yargs(arg)
  .usage('Usage: yargs-learn [command] <options>')
  ... // test api
  .argv;

注:

一般命令组成为: 主命令 command --option option-param

主命令, 即为 package.json 里配置的 bin 属性里的 key。
command, 为一般要实现的命令。
option, 选项,在命令语句中要 --option 使用,如果有别名则也可以 -alias,如 yargs-learn --help  等同于 yargs-learn -h
option-param,  option 的参数

脚手架测试环境搭建具体详情可以参看:前端脚手架实现原理

1 command

注册命令。

.command(cmd, desc, [builder], [handler])

cmd 为命令的名字; desc 为该命令的说明;[builder],生成器,用来注入命令所接受的选项,可以是一个对象,也可以是一个函数,接受 yargs 对象作为参数;[handler],一个函数,接受argv作为参数,命令执行后要做什么操作,可以在该函数内实现。

.command('get', 'get something', (yargs) => {
    yargs.option('url', {
      type: 'string', 
      alias: 'u',
      default: 'http://yargs.js.org/',
      description: 'yargs website'
    })
  }, (argv) => {
    console.log('argv', argv);
  })

.command({
  command: 'list [number]',
  aliases: ['ls','ll'], // 命令别名
  description: 'list description',
  builder: (yargs) => {},
  handler: (argv) => { console.log(argv); }

})

2 options

注册选项。

.option(key, [opt])
.options(key, [opt])
// 单个注册
.option('f', {
  alias: 'file',
  demandOption: true,
  default: '/etc/passwd',
  describe: 'x marks the spot',
  type: 'string'
})
// 多个注册
.options({
  debug: {
      type: 'Boolean',
      description: 'debug 模式',
      alias: 'd'
  },
  hideCli: {
      type: 'Boolean',
      hidden: true, // 隐藏命令不对外使用
      description: '隐藏命令'
  }
})

3 usage

用来描述语法。

.usage(<message|command>, [desc], [builder], [handler])

只接收一个字符串时,该字符串可以任意填写,一般用来描述命令的语法。 .usage() 也可以用来作 .command()使用(.usage() acts as an alias for .command()),设置默认的命令。

// 语法格式
.usage('Usage: yargs-learn [command] <options>')

// as an alias for .command() 时,第一个参数必须是以 $0 开头, $0 代表主命令。
// .positional() 功能等同于.option(), 不同的是 .positional() 只能在 [builder] 回调中使用
.usage('$0 <port>', 'start the application server', (yargs) => {
    yargs.positional('port', {
      describe: 'the port that your application should bind to',
      type: 'number'
    })
  }).argv

4 alias

设置option别名。

.alias('h', 'help')

一般在 .command() 和 .options() 中就可以为 option 设置别名。如果别名重复,则会覆盖。

5 wrap

设置输出内容的宽度。接受一个 number 类型的参数。 设为yargs(arg).terminalWidth(),为输出设备的最大宽度。

.wrap(number)

6 strict

严格模式, 输入错误的 option 时,会提示错误

.strict()

7 demandCommand

输入的命令个数,及个数不满足时的提示信息。

.demandCommand([min=1], [minMsg])

.demandCommand([min=1], [max], [minMsg], [maxMsg])
.demandCommand(1, 'You need at least one command before moving on')

8 epilogue

结尾提示。

.epilogue(str)
.epilogue('for more information, find our manual at http://example.com')

9 group

option 分组。

.group(key(s), groupName)
.group('version', 'Global Options')
.group(['help', 'version'], 'Global Options')

10 recommendCommands

在找不到命令时推荐一个名称类似的命令。

.recommendCommands()

11 fail

出现错误时的回调。

.fail(fn | boolean)
.fail(function (msg, err, yargs) {
    if (err) throw err // preserve stack
    console.error('You broke it!')
    console.error(msg)
    console.error('You should be doing', yargs.help())
    process.exit(1)
  })

// 防止yargs退出并打印失败消息
.fail(false)

parse

yargs(arg).argv 等于 yargs().parse(arg)

.parse([args], [context], [parseCallback])

三 测试代码

#!/usr/bin/env node

const yargs = require("yargs/yargs");
const { hideBin } = require("yargs/helpers");

/**
 * hideBin 用来解析参数, hideBin(process.argv) == process.argv.slice(2)。
 * require("yargs/yargs").hideBin == require("yargs/helpers").hideBin
 */
const arg = hideBin(process.argv);

console.log(yargs(arg).argv)
console.log(yargs().parse(arg))

yargs(arg)
  .usage('Usage: yargs-learn [command] <options>') // 标识语法格式
  .demandCommand(1, 'A command is required') // 最少的命令个数,及个数不够时的提示
  .strict() // 严格模式, 输入错误的 option 时,会提示错误
  .alias('v', 'version') // 注册别名  别名如果重复,会出现覆盖的情况
  .alias('h', 'help')
  //.wrap(500)
  .wrap(yargs(arg).terminalWidth()) // terminal宽度 接收number类型的参数
  .epilogue('footer description') // 结尾提示
  // 添加 option
  // .option('debug', {
  //   type: 'Boolean',
  //   description: 'debug 模式',
  //   alias: 'd'
  // })
  .options({
      debug: {
          type: 'Boolean',
          description: 'debug 模式',
          alias: 'd'
      },
      hideCli: {
          type: 'Boolean',
          hidden: true, // 隐藏命令不对外使用
          description: '隐藏命令'
      }
  })
  .group(['version'], 'Global Options') // 分组 参数:(option, 组名)
  .group(['help'], 'Global Options')
  .command(
    'init [name]', // command [options]
    'init project',  // description
    // builder 在命令执行之前处理
    (yargs) => {
      yargs.option('name', {
        type: 'string',
        description: 'name project',
        alias: 'n'
      })
    },
    // handler 命令执行之后处理
    (argv) => {
      console.log('argv', argv);
    }
  )
  .command({
    command: 'list [number]',
    aliases: ['ls','ll'],
    description: 'list description',
    builder: (yargs) => {},
    handler: (argv) => { console.log(argv); }

  })
  .recommendCommands() // 在找不到命令时推荐一个名称类似的命令
  // 失败处理,须搭配 recommendCommands 使用
  .fail((err, msg) => {
    console.log('err', err);
    console.log('msg', msg);
  })
  .argv;