如何编写一个Node.js文件,既可以从命令行调用,也可以从其他文件中使用'require()'进行调用?

3

我想编写一个 Node.js 源文件 (myCode.js),其中有一个名为 foo(arg1, arg2,..) 的函数,以便我可以...

$ node ./myCode.js arg1 arg2

以及

// myOtherCode.js
var foo = require('./mycode')

这是可能的吗?目前我有一小堆像这样编码的文件

return (
    function foo() {
        //...
    }
)()

我会从Node命令行中调用它,如下所示:

$ node ./myCode.js arg1 agr2

现在我想将它们串联成一个单独的JavaScript文件,在命令行中使用'node'或'npm script'调用它(因此需要'require()'不同文件中的所有功能)。但我也希望保留单独运行它们的能力,如果需要的话。

我知道当从shell提示符调用时,arg1、arg2将变为argv[2]、argv[3]等,而当被'require()'时,它们将成为函数参数。

这可能也意味着我需要向'require()'传递参数?我该怎么做呢?

[使用Node.js 8.x [LTS]版本,因此无法使用export/import语法]

2个回答

2
是的,这是可能的。您需要使用process.argv来检索传递的参数。
例如,如果我们需要在控制台中输出字符串“hello”,我们需要创建一个名为“fileName.js”的文件,其中包含以下代码:
 let firstArgument = process.argv[_.indexOf(process.argv, '--firstArgument') + 1];
 console.log(firstArgument);

然后在终端中执行以下命令。
 node ./fileName.js --firstArgument varValue

2

在处理命令行参数和编程包使用时,通常会有不同的入口点。在Node.js中解析CLI参数的常规方法是使用process.argv.slice(2),因为node和脚本名称是前两个参数。

对于包级别的可执行脚本,index.js入口点导出了foo函数:

module.exports = function foo(arg1, arg2) { /* ... */ };

考虑到foo需要字符串参数,bin/index.js CLI可执行脚本可以如下简洁:

require('..')(...process.argv.slice(2));

两者都可以在package.json中指定:

"main": "index.js",
"bin": { "foo": "bin/index.js" }

这可能意味着我需要向“require()”传递参数?我该如何实现?

无法将它们传递给require。如果脚本需要以编程方式接受参数,则应使用接受参数的工厂函数包装它。

一个快速而简单的解决方法是通过process.argv将参数传递给CLI可执行脚本。例如,可以使用帮助器函数以动态参数调用可执行脚本:

const decache = require('decache');

function loadCliModule(name, ...args) {
    decache(name);
    const originalArgv = process.argv;
    process.argv = [...process.argv.slice(2), ...args];
    const binModule = require(name);
    process.argv = originalArgv;
    return binModule;
}

这可以被用作:

const foo = invokeCliModule(require.resolve('./foo'), 'bar'); // foo expects process.argv[2]

注意,由于decache的工作方式,它只会取消缓存已加载的模块。如果子模块使用process.argv,则应相应地处理。
这不应该在生产环境中使用,因为这种方法是hacky的,但在测试中完全适用。
自然的限制是从CLI传递的参数是字符串,因此函数应包含样板代码将它们转换为预期的数据类型(数字、布尔值等)。出于这个原因,最好将程序化和CLI入口点分开。
如果有必要调用许多类似的脚本,这可能是一个实际问题,解决方案是创建单个CLI可执行脚本,使用类似于yargs的库处理参数,并根据此调用其他文件中的功能。

我正在尝试将一堆shell脚本转换为相应的Node.js文件。这些脚本用于测试另一个软件,并通过控制/主脚本运行,但也可以单独运行。我的Node.js文件现在处于每个文件单独运行的状态(node <file> arg1 arg2),但我希望将它们扩展到通过一个断言库(如tape)运行,其中我需要使用require()。每个文件都将返回OKNOTOK。因此,同一文件需要像一个函数一样运行。 - yogmk
这是问题中没有涉及到的重要细节。为了测试目的,使用hack来调用这些模块是完全可以接受的。我已经更新了答案。 - Estus Flask

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接