前端架构: 脚手架框架之yargs高级应用教程

这篇具有很好参考价值的文章主要介绍了前端架构: 脚手架框架之yargs高级应用教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

脚手架框架之yargs高级应用


1 )高级应用概述

  • 现在还用 xyzcli 这个脚手架,继续在这个项目中来看yargs的高级用法
  • 在 yargs 文档中, 给出了复杂应用的方式,这里做下详解
    • https://www.npmjs.com/package/yargs?activeTab=readme#complex-example
  • 这里主要关注 ↓
    • command
    • recommendCommands
    • fail

2 )command 应用案例

2.1 官方示例

  • 复杂应用案例,自定义 command
    #!/usr/bin/env node
    const yargs = require('yargs/yargs')
    const { hideBin } = require('yargs/helpers')
    
    yargs(hideBin(process.argv))
      // 注意 command的 四个参数
      .command('serve [port]', 'start the server', (yargs) => {
        return yargs
          .positional('port', {
            describe: 'port to bind on',
            default: 5000
          })
      }, (argv) => {
        if (argv.verbose) console.info(`start server on :${argv.port}`)
        serve(argv.port)
      })
      .option('verbose', {
        alias: 'v',
        type: 'boolean',
        description: 'Run with verbose logging'
      })
      .parse()
    
    • 这里 command 的四个参数分别是
      • 1 )command + options, 这里 serve [port]
        • 这里的serve是自定义的命令,如: $ xyzcli serve
        • 这里的 [port] 是 option,如: $ xyzcli serve --port
      • 2 )描述,这里是 start the server
        • 用于对前面命令和配置的补充描述
      • 3 )builder函数,这里是一个回调
        • builder是指在运行command之前做的一些事情
        • 这里会传入 yargs 对象
        • 比如在这里可以定义在这个 serve 命令中用到的 option
        • 这里定义了一个port参数,并给它一个5000的默认值
      • 4 )handler函数,用于具体执行 command 的行为
        • 比如这个 serve 命令启动了一个http的服务
        • 这个http服务就在这个 handler 函数中定义

2.2 在xyzcli中配置, 这里接上文走一个全量的代码

#!/usr/bin/env node

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

const arg = hideBin(process.argv);
const cli = yargs(arg)

cli
	.usage('Usage: xyzcli [command] <options>')
	.demandCommand(1, 'A command is required. Pass --help to see all available commands and options.')
	.strict()
	.alias('h', 'help')
	.alias('v', 'version')
	// .alias('d', 'debug')
	.wrap(cli.terminalWidth())
	.epilogue(dedent`
		Welcome to use xyzcli command line.
		We hope you guys work happily every day!

		For more information, please visit: https://xxx.com/xxx/xyzcli
	`)
	.options({
		debug: {
			type: 'boolean',
			describe: 'Bootstrap debug mode',
			alias: 'd' // 这里添加了,上面就可以忽略了,推荐写在这里
		}
	})
	.option('registry', {
		type: 'string',
		describe: 'Define global registry',
		alias: 'r',
		// hidden: true, // 这个就不会出现在提示中,但是可以作为开发调试使用 --ci
	})
	.group(['debug'], '开发选项:')
	.group(['registry'], '其他选项:')
	.command('init [name]', 'Init your project', (yargs) => {
		yargs
			.option('name', {
				type: 'string',
				describe: 'Name of a project',
        alias: 'n',
			})
	}, (argv) => {
		console.log(argv);
	})
	.argv;
  • 执行 $ xyzcli init,查看输出
    { _: [ 'init' ], '$0': 'xyzcli' }
    
  • 执行 $ xyzcli init --name xx,查看输出
    { _: [ 'init' ], name: 'xx', '$0': 'xyzcli' }
    
  • 执行 $ xyzcli init -h,查看输出
    xyzcli init [name]
    
    Init your project
    
    开发选项:
      -d, --debug  Bootstrap debug mode                                                              [布尔]
    
    其他选项:
      -r, --registry  Define global registry                                                       [字符串]
    
    选项:
      -n, --name     Name of a project                                                             [字符串]
      -h, --help     显示帮助信息                                                                    [布尔]
      -v, --version  显示版本号                                                                      [布尔]
    
    • 可见最上面出现一则帮助提示
      xyzcli init [name]
      
      Init your project
      
  • 执行 xyzcli init -d -r npm -n x-project, 查看输出
    {
      _: [ 'init' ], // _ 里面就是注册的 command 命令
      // d 和 debug 存在这两个option, 则为true
      d: true,
      debug: true,
      // r 和 registry 也同样
      r: 'npm',
      registry: 'npm',
      // n 是 name,项目名称为 x-project
      n: 'x-project',
      name: 'x-project',
      // $0 就是脚手架命令
      '$0': 'xyzcli'
    }
    
    • 注意,这种定义下,注意 alias 别名不能重复
    • 如果重复,覆盖了,就会出问题

2.3 参考 lerna 工程示例

  • 参考:https://github.com/lerna/lerna/blob/main/packages/lerna/src/index.ts
    // Bundled
    import { lernaCLI } from "@lerna/core";
    import changedCmd from "@lerna/commands/changed/command";
    import cleanCmd from "@lerna/commands/clean/command";
    import diffCmd from "@lerna/commands/diff/command";
    import execCmd from "@lerna/commands/exec/command";
    import importCmd from "@lerna/commands/import/command";
    import infoCmd from "@lerna/commands/info/command";
    import initCmd from "@lerna/commands/init/command";
    import listCmd from "@lerna/commands/list/command";
    import publishCmd from "@lerna/commands/publish/command";
    import runCmd from "@lerna/commands/run/command";
    import versionCmd from "@lerna/commands/version/command";
    
    import addCachingCmd from "./commands/add-caching/command";
    import repairCmd from "./commands/repair/command";
    import watchCmd from "./commands/watch/command";
    
    // Evaluated at runtime to grab the current lerna version
    const pkg = require("../package.json");
    
    module.exports = function main(argv: NodeJS.Process["argv"]) {
      const context = {
        lernaVersion: pkg.version,
      };
    
      const cli = lernaCLI()
        .command(addCachingCmd)
        .command(changedCmd)
        .command(cleanCmd)
        .command(createCmd)
        .command(diffCmd)
        .command(execCmd)
        .command(importCmd)
        .command(infoCmd)
        .command(initCmd)
        .command(listCmd)
        .command(publishCmd)
        .command(repairCmd)
        .command(runCmd)
        .command(watchCmd)
        .command(versionCmd);
    
      applyLegacyPackageManagementCommands(cli);
    
      return cli.parse(argv, context);
    };
    
  • 按照上述这种用法,找其中一条 .command(listCmd)
  • 定位到 import listCmd from "@lerna/commands/list/command";
    • https://github.com/lerna/lerna/blob/main/packages/lerna/src/commands/list/command.ts 发现内容很少
  • 再次查看全局配置: https://github.com/lerna/lerna/blob/main/tsconfig.base.json
    "@lerna/commands/list": ["libs/commands/list/src/index.ts"],
    
  • 定位到这里 https://github.com/lerna/lerna/blob/main/libs/commands/list/src/command.ts
    import { filterOptions, listableOptions } from "@lerna/core";
    import type { CommandModule } from "yargs";
    
    /**
     * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module
     */
    const command: CommandModule = {
      command: "list",
      aliases: ["ls", "la", "ll"],
      describe: "List local packages",
      builder(yargs) {
        listableOptions(yargs);
        return filterOptions(yargs);
      },
      async handler(argv) {
        return (await import(".")).factory(argv);
      },
    };
    
    export = command;
    
    • 可见这个 command 是一个对象,对象里有4项参数
  • 以上这个,是 Lerna 对yargs的内部应用,同样,在自己的脚手架中试验一下
    const cli = yargs(arg)
    
    cli
      .usage('Usage: xyzcli [command] <options>')
      .demandCommand(1, 'A command is required. Pass --help to see all available commands and options.')
      .strict()
      .alias('h', 'help')
      .alias('v', 'version')
      // .alias('d', 'debug')
      .wrap(cli.terminalWidth())
      .epilogue(dedent`
        Welcome to use xyzcli command line.
        We hope you guys work happily every day!
    
        For more information, please visit: https://xxx.com/xxx/xyzcli
      `)
      .options({
        debug: {
          type: 'boolean',
          describe: 'Bootstrap debug mode',
          alias: 'd' // 这里添加了,上面就可以忽略了,推荐写在这里
        }
      })
      .option('registry', {
        type: 'string',
        describe: 'Define global registry',
        alias: 'r',
        // hidden: true, // 这个就不会出现在提示中,但是可以作为开发调试使用 --ci
      })
      .group(['debug'], '开发选项:')
      .group(['registry'], '其他选项:')
      .command('init [name]', 'Init your project', (yargs) => {
        yargs
          .option('name', {
            type: 'string',
            describe: 'Name of a project',
            alias: 'n',
          })
      }, (argv) => {
        console.log(argv);
      })
      // 注意,这里
      .command({
        command: 'list',
        aliases: ['ls', 'la', 'll'],
        describe: 'List local package',
        builder: (yargs) => {},
        handler: (argv) => { console.log(argv); }
      })
      .argv;
    
  • 执行 $ xyzcli list, 查看输出
    { _: [ 'list' ], '$0': 'xyzcli' }
    
  • 执行 $ xyzcli ls, 查看输出
    { _: [ 'ls' ], '$0': 'xyzcli' }
    
  • 执行 $ xyzcli ll, 查看输出
    { _: [ 'll' ], '$0': 'xyzcli' }
    
  • 执行 $ xyzcli la, 查看输出
    { _: [ 'la' ], '$0': 'xyzcli' }
    
  • 以上就是 command 的两种用法

3 )recommendCommands 应用案例

const cli = yargs(arg)

cli
	.usage('Usage: xyzcli [command] <options>')
	.demandCommand(1, 'A command is required. Pass --help to see all available commands and options.')
	.strict()
	.recommendCommands() // 注意这里
	.alias('h', 'help')
	.alias('v', 'version')
	// .alias('d', 'debug')
	.wrap(cli.terminalWidth())
	.epilogue(dedent`
		Welcome to use xyzcli command line.
		We hope you guys work happily every day!

		For more information, please visit: https://xxx.com/xxx/xyzcli
	`)
	.options({
		debug: {
			type: 'boolean',
			describe: 'Bootstrap debug mode',
			alias: 'd' // 这里添加了,上面就可以忽略了,推荐写在这里
		}
	})
	.option('registry', {
		type: 'string',
		describe: 'Define global registry',
		alias: 'r',
		// hidden: true, // 这个就不会出现在提示中,但是可以作为开发调试使用 --ci
	})
	.group(['debug'], '开发选项:')
	.group(['registry'], '其他选项:')
	.command('init [name]', 'Init your project', (yargs) => {
		yargs
			.option('name', {
				type: 'string',
				describe: 'Name of a project',
				alias: 'n',
			})
	}, (argv) => {
		console.log(argv);
	})
	.command({
		command: 'list',
		aliases: ['ls', 'la', 'll'],
		describe: 'List local package',
		builder: (yargs) => {},
		handler: (argv) => { console.log(argv); }
	})
	.argv;
  • 上面加上 .recommendCommands() 之后, 尝试执行 $ xyzcli l, 查看输出
    Usage: xyzcli [command] <options>
    
    命令:
      xyzcli init [name]  Init your project
      xyzcli list         List local package                                             [aliases: ls, la, ll]
    
    开发选项:
      -d, --debug  Bootstrap debug mode                                                                 [布尔]
    
    其他选项:
      -r, --registry  Define global registry                                                          [字符串]
    
    选项:
      -h, --help     显示帮助信息                                                                       [布尔]
      -v, --version  显示版本号                                                                         [布尔]
    
    Welcome to use xyzcli command line.
    We hope you guys work happily every day!
    
    For more information, please visit: https://xxx.com/xxx/xyzcli
    
    是指 ls?
    
    • 看这最后,是指 ls?, 这个命令就是当你输入不全时,尝试对你进行提醒

4 )fail 应用案例


cli
	.usage('Usage: xyzcli [command] <options>')
	.demandCommand(1, 'A command is required. Pass --help to see all available commands and options.')
	.strict()
	.recommendCommands()
  // 注意这里
	.fail((msg, err) => {
		console.log('msg: ', msg)
		console.log('err: ', err)
	})
	.alias('h', 'help')
	.alias('v', 'version')
	// .alias('d', 'debug')
	.wrap(cli.terminalWidth())
	.epilogue(dedent`
		Welcome to use xyzcli command line.
		We hope you guys work happily every day!

		For more information, please visit: https://xxx.com/xxx/xyzcli
	`)
	.options({
		debug: {
			type: 'boolean',
			describe: 'Bootstrap debug mode',
			alias: 'd' // 这里添加了,上面就可以忽略了,推荐写在这里
		}
	})
	.option('registry', {
		type: 'string',
		describe: 'Define global registry',
		alias: 'r',
		// hidden: true, // 这个就不会出现在提示中,但是可以作为开发调试使用 --ci
	})
	.group(['debug'], '开发选项:')
	.group(['registry'], '其他选项:')
	.command('init [name]', 'Init your project', (yargs) => {
		yargs
			.option('name', {
				type: 'string',
				describe: 'Name of a project',
				alias: 'n',
			})
	}, (argv) => {
		console.log(argv);
	})
	.command({
		command: 'list',
		aliases: ['ls', 'la', 'll'],
		describe: 'List local package',
		builder: (yargs) => {},
		handler: (argv) => { console.log(argv); }
	})
	.argv;
  • 尝试执行 $ xyzcli lxx 故意给一个没有的命令,查看输出结果

    msg:  是指 ls?
    err:  undefined
    msg:  无法识别的选项:lxx
    err:  undefined
    
    • 这里输出了 2个 msg, 两个 err, 这里 err 都是 undefined
    • 在实际应用中,参考 lerna, 如下
  • 参考 lerna 中的应用 https://github.com/lerna/lerna/blob/main/libs/core/src/lib/cli.ts#L18文章来源地址https://www.toymoban.com/news/detail-828161.html

    .fail((msg, err: any) => {
      // certain yargs validations throw strings :P
      const actual = err || new Error(msg);
    
      // ValidationErrors are already logged, as are package errors
      if (actual.name !== "ValidationError" && !actual.pkg) {
        // the recommendCommands() message is too terse
        if (/Did you mean/.test(actual.message)) {
          // TODO: refactor to address type issues
          // eslint-disable-next-line @typescript-eslint/ban-ts-comment
          // @ts-ignore
          log.error("lerna", `Unknown command "${cli.parsed.argv._[0]}"`);
        }
    
        log.error("lerna", actual.message);
      }
    
      // exit non-zero so the CLI can be usefully chained
      cli.exit(actual.exitCode > 0 ? actual.exitCode : 1, actual);
    })
    

到了这里,关于前端架构: 脚手架框架之yargs高级应用教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端架构: 实现脚手架终端UI样式之ANSI escape code, Chalk, Ora介绍

    在脚手架当中实现命令行的UI显示 1 )概述 在命令行中,如果想实现除传统的常规文本以外的内容 比如想对字体进行加粗斜体下划线,包括对它改变颜色改变前景色改变后景色等等 需要借助一个叫做 ANSI escape code 这样的一个概念 它其实是一个标准,它可以用来控制光标的位

    2024年02月22日
    浏览(26)
  • 实现一个简单的前端脚手架

    前端脚手架概念 实现前端脚手架 随着前端工程化的概念越来越深入人心,脚手架应运而生。简单来说,「前端脚手架」就是指通过选择几个选项快速搭建项目基础代码的工具 前端脚手架可帮我们做什么? 可以帮助我们快速生成项目的基础代码 脚手架工具的项目模板经过了

    2024年02月03日
    浏览(26)
  • 和chatgpt学架构01-搭建项目脚手架

    今年3月份以来,chatgpt就热度不减。有了这种聊天机器人,就可以很方便的帮助我们提高。无论是我们独立创业还是做项目外包,拥有一套自己可以把握的脚手架还是必备的能力。 过去如果靠自己摸索,组装这么一套脚手架还是费事费力的。一个是涉及技术比较多,既要架构

    2024年02月16日
    浏览(24)
  • 前端如何搭建脚手架并在本地运行

    在开始搭建前,确保本机安装了node,为避免奇奇怪怪的问题 建议node版本16以上 使用过vue ,react,angular的同学都知道 ,应该对脚手架有一定的理解,比如vue-cli的 vue create myApp ,其中vue 就是vue-cli声明的一个命令,下来我们创建一个项目并声明自己的命令。 创建一个空的文件夹

    2024年02月20日
    浏览(29)
  • Vue的架构以及基于脚手架环境开发vue项目

    M:model 模型层(业务逻辑层),主要包含 JS 代码,用于管理业务逻辑的实现。 V:View 视图层,主要包括 HTML / CSS代码,用于管理 UI 的展示。 VM:viewModel (视图模型层),用于将data与视图层的 DOM 进行动态绑定。 基于脚手架环境开发Vue项目 制作web 从小作坊状态转向工程化开

    2024年02月01日
    浏览(30)
  • React应用(基于React脚手架)

    react 是前端三大框架中之一,而且大公司基本都在用react 包括百度也在使用 他有自己的独特的虚拟dom build-react-cli是帮助你快速创建生成react项目的脚手架工具,配置了多种可选择的不同类型项目模版。 xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目 包含了所有需

    2023年04月21日
    浏览(25)
  • 【前端】Vue2 脚手架模块化开发 -快速入门

    🎄欢迎来到@边境矢梦°的csdn博文🎄  🎄本文主要梳理Vue2 脚手架模块化开发 🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下 🫰🫰🫰 ,下次更新不迷路🎆 Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒🌓🌔🌕

    2024年02月10日
    浏览(40)
  • 小程序框架Mpx的下一代脚手架升级之路|滴滴开源

    导读 Mpx开源之路已经走过五个年头, 目前支持了滴滴内部全量的小程序业务开发,是滴滴开源委员会孵化的精品项目。 2022年至今,我们对 Mpx 框架进行了多项重要功能升级,包括组合式API开发规范、分包异步构建支持、单元测试能力建设和今天要重点介绍的@mpxjs/cli脚手架升

    2024年02月13日
    浏览(32)
  • 新鲜出炉的 MVVM 脚手架 —— KtArmor-MVVM,面试安卓系统架构

    } 通过 @BindViewModel 注解viewModel 变量,KtArmor-MVVM 通过 反射 ,自动创建 LoginViewModel 实例, 并赋值给 viewModel 变量。直接使用即可! @BaseUrl(API.BASE_URL) // 看这里!! interface ApiService { @POST(API.LOGIN) suspend fun login(@Query(“username”) username: String, @Query(“password”) password: String): BaseRe

    2024年04月10日
    浏览(33)
  • 使用vue脚手架搭建前端工程(附:搭配ElementUI来快速开发)

    目录 一、搭建过程 1. 全局安装webpack(打包工具) 2. 全局安装vue脚手架 3. 初始化vue项目 4. vue项目目录的简单介绍 二、执行流程分析 三、自己造一个组件案例 四、ElementUI的使用 1. 环境的引入 2. 一个简单使用 3. 使用它来快速搭建后台管理系统 五、总结 npm install webpack -g np

    2024年02月10日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包