使用 ES 模块在 Node.js 中使用相对路径导入

Importing using relative paths in Node.js with ES Modules

过去,每当我想在 Node.js 应用程序中使用相对路径时,我都会使用 app-module-path。如果我通过 .mjs 格式使用 ES 模块,我如何在某个目录路径变为相对路径时拥有相同的功能?

以另一种方式,我是否可以为目录分配别名,以便所有相对路径都相对于该别名,就像 ./ 是相对于当前路径的别名一样目录。

可以通过 monkey-patching 内置 module 模块为使用 require 加载的 CommonJS 模块的某些路径指定别名。

ES 模块提供了一种通过指定 custom ES module loader, as explained in .

来更改模块加载行为的方法

这样根源路径(将相对于加载器位置指定)可以映射到一些别名( 对于前端项目):

自定义-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

注意:如果您在最近的 package.json 中指定 "type": "module",则不需要使用 .mjs 扩展名。你可以保持无扩展。
注意 2:您可以将 src 字符串替换为您通常放置代码的位置,您甚至可以使用基于 process.env.NODE_ENV 的分辨率。
注 3:如果您将目录提供给 @,它将期望找到一个 index.js 文件。
注意4:您可以使用任何您想要的别名,只需替换正则表达式