Альтернатива для __dirname в узле при использовании флага --experimental-modules

Я использую флаг --experimental-modules при запуске моего приложения-узла, чтобы использовать модули ES6.

Однако, когда я использую этот флаг, __dirname недоступно. Есть ли альтернативный способ получить ту же строку, которая хранится в __dirname, совместимом с этим режимом?

Ответ 1

Начиная с Node.js 10.12 существует альтернатива, которая не требует создания нескольких файлов и обрабатывает специальные символы в именах файлов на разных платформах:

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

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

Ответ 2

Были предложения об экспонировании этих переменных через import.meta, но пока вам нужен хакерский обходной путь, который я нашел здесь:

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

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

Ответ 3

Я использовал:

import path from 'path';

const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname)));

decodeURI было важно: используемые пробелы и другие вещи в пути в моей тестовой системе.

path.resolve() обрабатывает относительные URL-адреса.

Ответ 4

import path from 'path';
const __dirname = path.join(path.dirname(decodeURI(new URL(import.meta.url).pathname)));

Этот код также работает в Windows

Ответ 5

Для узла 10.12 +...

Предполагая, что вы работаете с модулем, это решение должно работать, а также обеспечивает поддержку __filename.

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

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

Приятно то, что вы также всего в двух строках кода от поддержки require() для модулей CommonJS. Для этого вы бы добавили:

import { createRequireFromPath } from 'module';
const require = createRequireFromPath(__filename); 

Ответ 6

Я также попал в эту проблему, мое решение:

./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.

Ответ 8

Я сделал этот модуль es-dirname, который будет возвращать текущий сценарий dirname.

import dirname from 'es-dirname'

console.log(dirname())

Он работает как в скриптах CommonJs, так и в модулях ES как в Windows, так и в Linux.

Откройте там проблему, если возникла ошибка, так как скрипт работал до сих пор в моих проектах, но в некоторых других случаях он может не работать. По этой причине не используйте его в производственной среде. И это временное решение, так как я уверен, что команда Node.js выпустит надежный способ сделать это в ближайшем будущем.

Ответ 9

Я использую эту опцию, так как путь начинается с file:// просто удалите эту часть.

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

Ответ 10

Как указал Джефф, следующий код возвращает не путь к модулю, а рабочий каталог.

import path from 'path';
const __dirname = path.resolve();

работает с --experimental-modules