Альтернатива для __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
.
Ответ 7
Поскольку process.argv[1]
содержит полный путь к сценарию Node, вы можете просто
import path from 'path';
const __dirname = path.dirname(process.argv[1]);
Ответ 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