Возможны ли абсолютные (т.е. относительные к корню) пути к собственным узлам с помощью модуля ES с именем Import?
Обычно в Node можно использоватьNODE_PATH=./src"
сделать так, чтобы вместо:
import { foo } from '../../../bar'
Вы можете просто сделать:
import { foo } from 'src/bar'
Однако это работает только в том случае, если вы используетеesm
пакет (т.node -r esm
):NODE_PATH
не работает с собственными модулями ES (т.е. добавление"type": "module"
к ) ... так какая современная замена?
Я пробовал все следующее, и ни один из них, похоже, не работает (хотя я могу использовать их неправильно и буду рад любым разъяснениям):
- локальные файлы (т.е. `"dependencies": { "src": "file:./src",) - не удалось заставить это работать
- символические ссылки (т.е. добавление символической ссылки из
node_modules/src
кproject-root/src
) - который импортирует файл как пакет CommonJS, а не пакет ES, что означает, что именованный импорт не работает. - рабочие места (т.
"workspaces": ["src"],
вpackage.json
) - та же проблема: нет именованного импорта - импорт (т.
"imports": {"#src": "./src"}
) - игнорирует--experimental-specifier-resolution=node
флаг (поэтому он работает только в том случае, если я хочу пройти и вручную добавить.js
к каждому импорту в моем проекте) - пользовательские загрузчики (т.е. создание
loader.js
файл и с помощьюnode --loader loader.js
) - Я не мог понять, как это сделать, так как документации по кастомным загрузчикам почти нет
В идеале я бы предпочел не реализовывать весь Babel/Webpack/Typescript/и т.д. в моем проекте, просто заменитьNODE_PATH=./src
, но кажется, что добавление какого-то такого инструмента - единственный способ сейчас?
1 ответ
Это похоже на единственный жизнеспособный вариант ... если вы хотите импортировать относительно корня И вы не хотите указывать.js
расширение ... заключается в использовании пользовательского загрузчика.
Для справки, тот, который я сделал для этого, был:
import path from 'path';
import fs from 'fs';
export function resolve(originalSpecifier, context, defaultResolver) {
let specifier = originalSpecifier;
try {
// All my root-relative imports start with "src/"; if you
// have other folders you'll need to account for them here
if (specifier.startsWith('src')) {
specifier = specifier.replace(/^src/, path.resolve('.') + '/src');
// If the import is for a directory, get its index.js file
const itExists = fs.existsSync(specifier);
let isDirectory = false;
try {
isDirectory = fs.lstatSync(specifier).isDirectory();
} catch (err) {}
specifier = itExists && isDirectory ? `${specifier}/index` : specifier;
// Add the ".js" extension if not specified
specifier += specifier.endsWith('.js') ? '' : '.js';
return {
format: 'module',
url: new URL(specifier, context.parentURL).href,
};
}
} catch (err) {
console.error(err);
}
// If we're not handling our special cases, just use the
// default handler
return defaultResolver(specifier, context);
}
Затем вы можете использовать этот загрузчик с--loader
вариант, напр.
node --loader loader.js index.js
Тем не менее, стоит отметить, что загрузчик все еще находится в стадии разработки и может измениться (сделав указанный выше загрузчик недействительным) в будущем. Вероятно, где-то в 2030 году, учитывая, насколько медленно развивается Node org ;)