如何在ESM模式下为Yargs命令传递参数?
问题
我编写了一个使用Yargs命令的简单Node.js应用,基于CommonJS构建时运行完全正常。现在尝试将其改写为ESM版本,但遇到了参数传递的问题:
在CommonJS版本中,通过控制台命令后的--flag=value标志,可以向命令的handler函数传递参数,这些参数会以键值对形式出现在handler的params对象中。示例如下:
控制台执行命令:
node index add --someParam=some_param
Handler函数中的输出:
{ ...add command... handler(params) { console.log(params) // { _: [ 'list' ], someParam: 'some_param', '$0': 'index' } } }
但在ESM版本中,无论添加什么额外标志,params始终只包含:
{ _: [ 'add' ], '$0': 'index' }
请问该如何在ESM版本中正常从控制台向Yargs命令传递参数?
完整代码
CommonJS版本
const yargs = require('yargs'); const chalk = require('chalk'); const {addNote, printNotes, deleteNote} = require("./notesController"); const add = { command: 'add', describe: 'Add new note to list', builder: { title: { type: 'string', describe: 'Note title', demandOption: true, } }, handler(params) { console.log(params); const {title} = params; addNote(title); console.log(chalk.green(`${title} added to list`)); }, }; yargs.command(add); yargs.parse();
ESM版本
import yargs from 'yargs' import chalk from 'chalk'; import { addNote, printNotes, deleteNote } from "./notesController.js"; const { green, red, bgRed } = chalk; const add = { command: 'add', describe: 'Добавить новую заметку в список', builder: { title: { type: 'string', describe: 'Заголовок заметки', demandOption: true, } }, handler(params) { addNote(params.title); console.log(chalk.green(`${params.title} added to list`)); }, }; const commands = yargs(process.argv[2]) .command(add) commands.parse();
解决方案
问题出在ESM版本中初始化Yargs的方式错误。你只传递了process.argv[2],这截断了后续的参数,导致Yargs无法解析--title这类标志。
正确的做法是传递完整的process.argv.slice(2),或者直接使用Yargs提供的工具方法处理参数,修改后的ESM版本代码如下:
import yargs from 'yargs' import { hideBin } from 'yargs/helpers' // 推荐使用这个工具方法处理argv import chalk from 'chalk'; import { addNote, printNotes, deleteNote } from "./notesController.js"; const { green, red, bgRed } = chalk; const add = { command: 'add', describe: 'Добавить новую заметку в список', builder: { title: { type: 'string', describe: 'Заголовок заметки', demandOption: true, } }, handler(params) { addNote(params.title); console.log(chalk.green(`${params.title} added to list`)); }, }; // 推荐方式:使用hideBin自动过滤Node.js默认的前两项argv yargs(hideBin(process.argv)) .command(add) .parse(); // 替代方式1:手动截取参数部分 // yargs(process.argv.slice(2)) // .command(add) // .parse(); // 替代方式2:不传递参数,Yargs会自动处理 // yargs() // .command(add) // .parse();
解释:
- Node.js中
process.argv数组的前两项是Node可执行文件路径和当前脚本路径,从第三项开始才是用户输入的命令与参数。 hideBin是Yargs提供的工具方法,会自动过滤掉前两项无效内容,返回用户实际输入的参数部分,比手动slice(2)更可靠。- 之前只传递
process.argv[2],仅传入了命令名add,后续的--title=xxx参数被丢弃,所以handler无法获取到目标参数。
现在执行命令node index.js add --title="测试标题",handler的params里就能正常获取到title参数了。
内容的提问来源于stack exchange,提问作者Александр Каплан
相关产品推荐
相关产品推荐

