我在运行节点应用程序时使用标志--experimental-modules
以使用ES6模块。
但是,当我使用此标志时,元变量__dirname
不可用。是否有另一种方法可以获得与此模式兼容的__dirname
中存储的相同字符串?
答案 0 :(得分:25)
在Node.js 10中,有一种不需要创建多个文件的替代方案:
import path from 'path';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
答案 1 :(得分:19)
有关于通过import.meta
公开这些变量的建议,但就目前而言,您需要一个我发现的here hacky解决方法:
// expose.js
module.exports = {__dirname};
// use.mjs
import expose from './expose.js';
const {__dirname} = expose;
答案 2 :(得分:9)
2021年最规范的方式
import { URL } from 'url'; // in Browser, the URL in native accessible on window
const __filename = new URL('', import.meta.url).pathname;
// Will contain trailing slash
const __dirname = new URL('.', import.meta.url).pathname;
忘记 join
从当前文件创建路径,只需使用 URL
const pathToAdjacentFooFile = new URL('./foo.txt', import.meta.url).pathname;
const pathToUpperBarFile = new URL('../bar.json', import.mera.url).pathname;
答案 3 :(得分:8)
在大多数情况下,使用 Node.js 原生的内容(带有 ES 模块),而不是外部资源,在大多数情况下使用 __filename
和 __dirname
完全没有必要< /强>。大多数(如果不是全部)用于读取(流)的本机方法都支持 new URL
+ import.meta.url
,正如官方文档本身所建议的那样:
正如您在方法说明中所见,path
参数显示了支持的格式,其中包括 <URL>
,示例:
方法 | 路径参数支持 |
---|---|
fs.readFile(path[, options], callback) |
<string> 、<Buffer> 、<URL> 、<integer> |
fs.readFileSync(path[, options]) |
<string> 、<Buffer> 、<URL> 、<integer> |
fs.readdir(path[, options], callback) |
<string> 、<Buffer> 、<URL> |
fs.readdirSync(path[, options]) |
<string> 、<Buffer> 、<URL> 、<integer> |
fsPromises.readdir(path[, options]) |
<string> 、<Buffer> 、<URL> |
fsPromises.readFile(path[, options]) |
<string> 、<Buffer> 、<URL> 、<FileHandle> |
因此,使用 new URL('<path or file>', import.meta.url)
可以解决问题,您无需处理字符串并创建稍后要连接的变量。
示例:
了解如何在不需要 __filename
或任何解决方法的情况下读取与脚本相同级别的文件:
import { readFileSync } from 'fs';
const output = readFileSync(new URL('./foo.txt', import.meta.url));
console.log(output.toString());
列出脚本目录下的所有文件:
import { readdirSync } from 'fs';
readdirSync(new URL('./', import.meta.url)).forEach((dirContent) => {
console.log(dirContent);
});
<块引用>
注意:在示例中,我使用同步函数只是为了更容易复制和执行。
如果打算制作一个依赖第三方的“自己的日志”(或类似的东西),那么手动完成一些事情是值得的,但在语言和 Node.js 中这是没有必要的,用 {{ 1}} 完全有可能不依赖于 ESMODULES
和 __filename
,因为带有 __dirname
的原生资源已经解决了。
请注意,如果您有兴趣在战略时刻使用诸如 new URL
之类的东西并且需要来自主脚本的绝对路径,您可以结合使用 require
(仅限 Node.js v12.2.0 +)使用 module.createRequire(filename)
在当前脚本级别以外的级别加载脚本,因为这已经有助于避免需要 import.meta.url
,示例使用 __dirname
和 import.meta.url
:>
module.createRequire
来自import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// foo-bar.js is a CommonJS module.
const fooBar = require('./foo-bar');
fooBar();
的来源:
foo-bar.js
这类似于使用没有“ECMAScript 模块”:
module.exports = () => {
console.log('hello world!');
};
答案 4 :(得分:3)
我用过:
import path from 'path';
const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname)));
decodeURI
很重要:测试系统路径中的已用空间和其他内容。
path.resolve()
处理相对网址。
答案 5 :(得分:1)
import path from 'path';
const __dirname = path.join(path.dirname(decodeURI(new URL(import.meta.url).pathname)));
此代码也可在Windows上使用
答案 6 :(得分:0)
我也遇到了这个问题,我的解决方案:
<强> ./ SRC / app.mjs:强>
app.set('views', path.join(path.resolve('./src'), 'views'));
以下是有关我的文件夹组织的信息:
<强> ./ index.mjs 强>
import server from './src/bin/www.mjs';
server.start();
<强> ./的package.json 强>
"scripts": {
"start": "node --experimental-modules ./index.mjs"
},
它在我的Windows PC上以__dirname
返回正确的路径。
答案 7 :(得分:0)
我制作了此模块es-dirname,该模块将返回当前脚本的目录名。
import dirname from 'es-dirname'
console.log(dirname())
它在 Windows 和 Linux 上的 CommonJs 脚本和 ES模块中均可工作。
如果由于我的项目中的脚本到目前为止一直在运行而发生错误,请在此处打开一个问题,但是在某些其他情况下可能会失败。因此,请勿在生产环境中使用它。这是一个临时解决方案,因为我确信Node.js团队将在不久的将来发布一种强大的方法来实现这一目标。
答案 8 :(得分:0)
对于节点10.12 + ...
假设您正在使用模块工作,则此解决方案应该可以工作,并且还为您提供__filename支持
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
令人高兴的是,距CommonJS模块的require()仅有两行代码。为此,您需要添加:
import { createRequireFromPath } from 'module';
const require = createRequireFromPath(__filename);
答案 9 :(得分:0)
我使用此选项,因为路径以 Align(
alignment: Alignment.bottomCenter,
widthFactor: 1.0,
heightFactor: 1.0,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(color: Colors.deepPurpleAccent, shape: BoxShape.circle),
child: IconButton(icon: Icon(Icons.search), onPressed: (){}),
),
)
开头,只需删除该部分即可。
file://
答案 10 :(得分:-1)
Geoff指出以下代码不是返回模块路径,而是返回工作目录。
import path from 'path';
const __dirname = path.resolve();
与--experimental-modules
答案 11 :(得分:-2)
process.cwd()
摘自文档:
process.cwd()
方法返回当前的工作目录。 Node.js进程。