【问题标题】:Importing using relative paths in Node.js with ES Modules在带有 ES 模块的 Node.js 中使用相对路径导入
【发布时间】:2018-12-29 08:49:57
【问题描述】:

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

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

【问题讨论】:

  • 每当我想在我的 Node.js 应用程序中使用相对路径时,我都会使用 app-module-path - 你是如何使用它的?不清楚你在问什么。 ES 和 CJS 模块以类似的方式解析。
  • 它们以类似的方式解决,但是一旦我使用 import 而不是 require 导入 app-module-path,我就会在终端中遇到神秘错误。
  • 如果您有具体问题,请说明并提供stackoverflow.com/help/mcve。对含糊问题的回答不一定有助于解决问题。
  • 我想要一种不必在我的 Node.js 项目中的任何地方使用 ../ 的方法。 app-module-path 允许我通过在根目录中调用 require('app-module-path/register') 来做到这一点。这样我就可以从项目的任何位置引用根目录中的所有文件夹,例如require('some-directory/a-file'),即使该文件位于根目录中。似乎没有任何解决方案可以使用导入语法来做到这一点。 Webpack 有目录别名,所以我认为必须有一个 Node.js 方式。

标签: node.js es6-modules mjs


【解决方案1】:

可以通过猴子补丁内置 module 模块为加载有 require 的 CommonJS 模块的某些路径提供别名。

ES 模块提供了一种通过指定custom ES module loader 来更改模块加载行为的方法,如this related answer 中所述。

这样根源路径(将相对于加载器位置指定)可以映射到某个别名(前端项目为@ is conventional):

custom-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)处理此代码的方式。

【讨论】:

    【解决方案2】:

    一个更多的 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:你可以使用任何你想要的别名,只需替换正则表达式

    【讨论】:

      猜你喜欢
      • 2016-12-01
      • 1970-01-01
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      相关资源
      最近更新 更多