Node.js 快速开发 cli 应用攻略 - 坑篇
「哇夭寿拉,文章都按照上下章来写啦」
因为一直找不到时间写,上次匆匆做完了介绍,所以开个下集谈谈几个库遇到的坑。
commander
commander 的 bug 确实挺多的,所以下一个坑准备试试 yargs
这个库(差点就准备自己写了 OTZ)。
argument 'domain' (and probably others) cause naming collision
本身我们提供了一个 domain
选项进行配置,但是后来发现使用这个选项就会报错……换了个名字就好了。于是翻了一下 issue……看到了一串「保留字」,就是这串保留字让我坚定了下次再也不用的决心:
[ 'Command',
'Option',
'__defineGetter__',
'__defineSetter__',
'__lookupGetter__',
'__lookupSetter__',
'__proto__',
'_allowUnknownOption',
'_args',
'_events',
'_execs',
'_maxListeners',
'_name',
'action',
'addImplicitHelpCommand',
'addListener',
'alias',
'allowUnknownOption',
'apply',
'args',
'arguments',
'bind',
'call',
'caller',
'command',
'commandHelp',
'commands',
'constructor',
'description',
'domain',
'emit',
'executeSubCommand',
'hasOwnProperty',
'help',
'helpInformation',
'isPrototypeOf',
'largestOptionLength',
'length',
'listeners',
'missingArgument',
'name',
'normalize',
'on',
'once',
'option',
'optionFor',
'optionHelp',
'optionMissingArgument',
'options',
'opts',
'outputHelp',
'parse',
'parseArgs',
'parseExpectedArgs',
'parseOptions',
'propertyIsEnumerable',
'prototype',
'rawArgs',
'removeAllListeners',
'removeListener',
'setMaxListeners',
'toLocaleString',
'toString',
'unknownOption',
'usage',
'valueOf',
'variadicArgNotLast',
'version' ]
如果你要使用保留字就会出现上述错误,并在后头说 3.0 会修复这个问题——然而一年过去了并没有_____
相关 issue: argument 'once' (and probably others) cause naming collision #404
git style commands
在一个「比较大」型的 cli 中,我们可能会想把子命令作为一个「分类」作用,也就是 sub sub command
去决定究竟做什么事情。
如果我们要执行一个添加 token
指令,大致有三种设计:
$ wang token add abcdefg
$ wang token:add abcdefg
$ wang add-token abcdefg
要实现第一种,目前需要使用 Git-style sub-commands,但是实际查了 issue 之后,感觉也有点问题,比如必须要是不带后缀的文件。命名必须是命令-子命令-sub sub command-...
的形式去解析每一层,虽然也可以写 bin
去映射,但是当时觉得和命令名耦合会不会不太好,最终自己实现了一套。
相关 issue: Sub Sub command issues #527
网络库
axios 与 form-data
axios 只有在浏览器环境才提供 form-data
的支持,所以额外使用了一个 form-data
库用于发送请求,当发送布尔值时发生了:
Uncaught TypeError: first argument must be a string or Buffer
at ClientRequest.OutgoingMessage.write (_http_outgoing.js:433:11)
at FormData.ondata (stream.js:51:26)
at FSReqWrap.oncomplete (fs.js:95:15)
感觉非常哲学,后来发现是因为 Boolean 的锅,必须要是 String 才可以,执行 Boolean 的 toString()
方法手动处理之后就能被正确处理了。
植入部分
如果您觉得文章不错,可以通过赞助支持我。
如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。
界面好简洁漂亮
11