Возможны ли абсолютные (т.е. относительные к корню) пути к собственным узлам с помощью модуля 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 ;)

Другие вопросы по тегам