为了使用ES6模块,我在运行Node应用程序时使用了——experimental-modules标志。
然而,当我使用这个标志时,元变量__dirname不可用。是否有另一种方法来获得与此模式兼容的存储在__dirname中的相同字符串?
为了使用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("/"));
其他回答
因为其他答案虽然有用,但没有涵盖跨平台情况(Windows POSIX)和/或路径解析,而不是__dirname或__filename,在所有地方重复这种代码有点冗长:
import { dirname, join } from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const somePath = join(__dirname, '../some-dir-or-some-file')
我刚刚发布了一个名为esm-path的NPM包来帮助完成这种循环任务,希望它也能对其他人有用。
它有文档记载,但在这里如何使用它:
import { getAbsolutePath } from 'esm-path'
const currentDirectoryPath = getAbsolutePath(import.meta.url)
console.log(currentDirectoryPath)
const parentDirectoryPath = getAbsolutePath(import.meta.url, '..')
console.log(parentDirectoryPath)
// Adapt the relative path to your case
const packageJsonFilePath = getAbsolutePath(import.meta.url, '../package.json')
console.log(packageJsonFilePath)
// Adapt the relative path to your case
const packageJsonFilePath = getAbsolutePath(import.meta.url, '..' , 'package.json')
console.log(packageJsonFilePath)
正如Geoff指出的那样,下面的代码返回的不是模块的路径,而是工作目录。
import path from 'path';
const __dirname = path.resolve();
使用——experimental-modules
节点10.12 +…
假设你正在从一个模块中工作,这个解决方案应该可以工作,并且还提供了__filename支持
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
好的事情是,你也只需要两行代码就可以支持CommonJS模块的require()。为此,你可以补充:
import { createRequireFromPath } from 'module';
const require = createRequireFromPath(__filename);
不管你是否同意使用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,也许有改进。
您可以使用来自新的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;
};