为了使用ES6模块,我在运行Node应用程序时使用了——experimental-modules标志。

然而,当我使用这个标志时,元变量__dirname不可用。是否有另一种方法来获得与此模式兼容的存储在__dirname中的相同字符串?


当前回答

我使用这个选项,因为路径以file://开始,只需删除该部分。

const __filename = import.meta.url.slice(7);
const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));

其他回答

已经有人提议通过导入公开这些变量。meta,但现在,你需要一个hack的工作,我在这里发现:

// expose.js
module.exports = {__dirname};

// use.mjs
import expose from './expose.js';
const {__dirname} = expose;
process.cwd()

从文档:

process.cwd()方法返回 node . js的过程。

您可以使用来自新的Error()的堆栈。这个错误不需要被抛出,也不会停止程序的执行。堆栈的第一行始终是错误及其消息,第二行是调用错误的文件。

由于这是一个方法(可能在util.js文件中),getDirname()调用的实际位置实际上是错误堆栈的第三行。

export const getDirname = () => {
    // get the stack
    const { stack } = new Error();
    // get the third line (the original invoker)
    const invokeFileLine = stack.split(`\n`)[2];
    // match the file URL from file://(.+)/ and get the first capturing group
    //     the (.+) is a greedy quantifier and will make the RegExp expand to the largest match
    const __dirname = invokeFileLine.match(/file:\/\/(.+)\//)[1];
    return __dirname;
};

Node.js 10.12有一个替代方案,不需要创建多个文件,并处理跨平台文件名中的特殊字符:

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
import path from 'path';
const __dirname = path.join(path.dirname(decodeURI(new URL(import.meta.url).pathname))).replace(/^\\([A-Z]:\\)/, "$1");

这段代码也适用于Windows。(替换在其他平台上是安全的,因为路径。join只在Windows上返回反斜杠分隔符)