在Node使用CommonJS模块时,可以使用require.main === module
来检测脚本是否从命令行运行。
当使用Node的ES模块(带有--experimental-modules
标志)时,检测脚本是否从命令行运行的等效方法是什么?
在Node使用CommonJS模块时,可以使用require.main === module
来检测脚本是否从命令行运行。
当使用Node的ES模块(带有--experimental-modules
标志)时,检测脚本是否从命令行运行的等效方法是什么?
使用
if (import.meta.url === `file://${process.argv[1]}`) {
// module was not imported but called directly
}
详细信息请参阅MDN文档中的import.meta
。
可能更加健壮,但需要通过额外导入(通过Rich Harris)实现。
import { pathToFileURL } from 'url'
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
// module was not imported but called directly
}
package.json
文件中通过bin
属性公开的cli脚本,会有所疏漏。node_modules/.bin
文件夹中创建符号链接。可以通过npx
或作为package.json
中scripts
对象定义的脚本来调用这些脚本。那种情况下,process.argv[1]
是符号链接而不是import.meta.url
引用的实际文件。file://
url,否则在不同平台上它将无法正常工作。import { realpathSync } from "fs";
import { pathToFileURL } from "url";
function wasCalledAsScript() {
// We use realpathSync to resolve symlinks, as cli scripts will often
// be executed from symlinks in the `node_modules/.bin`-folder
const realPath = realpathSync(process.argv[1]);
// Convert the file-path to a file-url before comparing it
const realPathAsUrl = pathToFileURL(realPath).href;
return import.meta.url === realPathAsUrl;
}
if (wasCalledAsScript()) {
// module was executed and not imported by another file.
}
我本来想将这个发表为对已被接受的答案的评论,但显然我的新账户不允许进行评论。
import.meta.main
属性。 传送门。if (import.meta.url === `file://${process.argv[1]}`) // module was not imported but called directly
。 - Janoshimport.meta.url === url.pathToFileURL(process.argv[1])
(来自 rich harris 在 Twitter 上的消息) - forivallmodule
,但在ES模块中根本不存在。是的,这里存在不一致之处,即ES模块是没有module
变量的东西。typeof v
是否为字符串(而非值!)'undefined'
来检查未定义的变量。const inCommonJs = typeof module !== 'undefined';
console.log(`inCommonJs = ${inCommonJs}`);
.cjs
和.mjs
文件中,我们将得到正确的答案:$ node foo.mjs
inCommonJs = false
$ cp foo.mjs foo.cjs
$ node foo.cjs
inCommonJs = true
我喜欢 import.meta.url === `file://${process.argv[1]}`
,但在 Windows 的 bash shell 中无法正常工作。这是一个替代方案,只检查基本名称:
const runningAsScript = import.meta.url.endsWith(path.basename(process.argv[1]));
看起来现在有一种已记录的方法可以做到这一点:
if (require.main === module) {
console.log('executed directly');
. . .
}