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

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


当前回答

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

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

// use.mjs
import expose from './expose.js';
const {__dirname} = expose;

其他回答

另一个选择

import {createRequire} from 'module'; // need node v12.2.0

const require = createRequire(import.meta.url);
const __dirname = require.resolve.paths('.')[0];
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);


// do not use the following code which is bad for CJK characters
const __filename = new URL('', import.meta.url).pathname;

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

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

// use.mjs
import expose from './expose.js';
const {__dirname} = expose;

不管你是否同意使用global,我发现这是记忆和重构现有代码的最简单方法。

在代码执行的早期放置:

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

global.___filename = (path) => {
  return fileURLToPath(path);
};

global.___dirname = (path) => {
  return dirname(global.___filename(path));
};

然后在任何需要dirname或filename的文件中:

___filename(import.meta.url)
___dirname(import.meta.url)

当然,如果有宏,我就不需要传递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上返回反斜杠分隔符)