Импорт с использованием относительных путей в Node.js с модулями ES
В прошлом я использовал app-module-path
всякий раз, когда я хотел иметь относительные пути в моих приложениях Node.js. Если я использую модули ES через .mjs
формат, как у меня такая же функциональность, когда определенный путь к каталогу становится относительным?
В качестве альтернативы, я бы мог вместо этого назначить псевдоним для каталога, чтобы все относительные пути относились к этому псевдониму так же, как ./
является псевдонимом пути относительно текущего каталога.
3 ответа
Использование свойства «Импорт»
С марта 2023 года хороший способ исключить относительные пути NodeJS — использоватьimports
собственность вpackage.json
. Для получения дополнительной информации, пожалуйста, обратитесь к этому сообщению:
- .
В приведенных ниже кодах #root — это корень проекта.
(Пожалуйста, поддержите этот ответ и Как импортировать файлы JavaScript в NodeJS, используя пути к файлам из корня проекта?этот пост, если они вам помогут. Спасибо!)
Для сценариев JavaScript в стиле CommonJS:
// package.json
{
"imports": {
"#root/*.js": "./*.js"
}
}
// main.js:
const Source = require('#root/path/to/Source.js');
// Source.js:
module.exports = class Source {
// ...
}
Для сценариев JavaScript в стиле ECMAScript:
// package.json:
{
"type" : "module",
"imports": {
"#root/*.js": "./*.js"
}
}
// main.js
import { Source } from '#root/path/to/Source.js';
// Source.js:
export class Source {
// ...
}
Преимущества:
Нет необходимости «импортировать» или «требовать» каких-либо дополнительных пакетов (нет Babel.js, нет Webpack, нет RequireJS). После установки NodeJS этот метод работает «из коробки».
Связи IDE работают должным образом (щелкните имя класса, удерживая клавишу Ctrl, чтобы перейти непосредственно к исходному файлу. Кроме того, перемещение исходного файла (путем перетаскивания) автоматически обновит ссылки на пути к файлу. Протестировано на
WebStorm 2022.3.2
иVS Code 1.76.2
.)Работает с обоими
.mjs
(система модулей ECMAScript) и.cjs
(CommonJS) типы файлов. Пожалуйста, ознакомьтесь с этой справочной публикацией по .cjs и .mjs.Нет необходимости изменять зарезервированные
node_modules
каталогНет необходимости настраивать какие-либо ссылки на файлы Linux на уровне ОС.
Можно дать псевдонимы определенным путям для модулей CommonJS, которые загружены с require
встроенный в мартышки module
модуль.
Модули ES предоставляют способ изменить поведение загрузки модуля, указав пользовательский загрузчик модуля ES, как объяснено в этом связанном ответе.
Таким образом, путь к корневому источнику (который будет указан относительно местоположения загрузчика) может быть сопоставлен с некоторым псевдонимом (@
обычен для внешних проектов):
таможенно-loader.mjs
import path from 'path';
const ROOT_PATH = new URL(path.dirname(import.meta.url) + '/src').pathname;
export function resolve(specifier, parentModuleURL, defaultResolver) {
specifier = specifier.replace(/^@/, ROOT_PATH);
return defaultResolver(specifier, parentModuleURL);
}
Который используется как:
node --experimental-modules --loader ./custom-loader.mjs ./app.mjs
Обратите внимание, что это обеспечивает поведение, которое не является естественным для модулей ES, это может повлиять на то, как этот код обрабатывается другими инструментами, такими как IDE.
Более версия 2019 года, работающая для модулей ES.
Самый простой способ, который я нашел до сих пор, - использовать экспериментальную функцию --loader
.
Я использую что-то подобное, чтобы иметь возможность требовать import { SOME_CONSTANT } from '@config'
или import { createConnection } from '@server/connection'
.
Код загрузчика:
import path from 'path'
import fs from 'fs'
export function resolve (specifier, parentModuleURL, defaultResolver) {
specifier = specifier.replace(/^@/, path.resolve('.') + '/src/')
specifier = fs.existsSync(specifier) && fs.lstatSync(specifier).isDirectory() ? `${specifier}/index` : specifier
specifier += '.js'
return defaultResolver(specifier, parentModuleURL)
}
потом node --experimental-modules --loader ./moduleResolver.js ./myScriptWithoutExtension
ПРИМЕЧАНИЕ: вам не нужно использовать .mjs
расширение, если вы укажете "type": "module"
в ближайшем package.json
. Вы можете оставаться без продления.
ПРИМЕЧАНИЕ 2: вы можете заменитьsrc
строка, в которую вы обычно помещаете свой код, вы могли бы даже иметь process.env.NODE_ENV
на основе разрешения.
ПРИМЕЧАНИЕ 3: Если вы дадите каталог@
, он будет ожидать найти index.js
файл.
ПРИМЕЧАНИЕ 4: вы можете использовать любой, какой хотите, для псевдонима, просто замените регулярное выражение