javascript - ES 模块命名导入是否可以实现 native Node 绝对(即根相对)路径?

标签 javascript node.js esmodules

通常在 Node 中可以使用NODE_PATH=./src" 来代替:

import { foo } from '../../../bar'

你可以这样做:

import { foo } from 'src/bar'

但是,只有在使用 esm 包(即 node -r esm)时才有效:NODE_PATH doesn' t 使用原生 ES 模块(即添加 "type": "module"package.json)...那么现代的替代品是什么?

我已经尝试了以下所有方法,但似乎都不起作用(尽管我可能没有正确使用它们,并且欢迎任何澄清):

  • 本地文件(即 `"dependency": { "src": "file:./src",) - 无法使其正常工作
  • 符号链接(symbolic link)(即从 node_modules/src 添加符号链接(symbolic link)到 project-root/src) - 将文件导入为 CommonJS包,而不是 ES 包,这意味着命名导入不起作用
  • 工作区(即package.json中的"workspaces": ["src"],) - 同样的问题:没有命名导入
  • 导入(即"imports": {"#src": "./src"}) - 忽略--experimental-specifier- resolution=node 标志(因此,只有当我想检查并手动将 .js 添加到项目中的每个导入中时,它才有效)
  • 自定义加载程序(即制作 loader.js 文件并使用 node --loader loader.js) - 我不能弄清楚如何进行这项工作,因为几乎没有关于自定义加载程序的文档

理想情况下,我不想实现所有 Babel/Webpack/Typescript/etc。在我的项目中,只是替换 NODE_PATH=./src,但似乎添加一些此类工具是现在唯一的方法?

最佳答案

这看起来是唯一可行的选择...如果您想要相对根导入并且不想指定 .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

但是,值得注意的是,加载程序仍在开发中,并且将来可能会发生变化(使上述加载程序无效)。考虑到 Node 组织的开发速度有多慢,可能是 2030 年的某个时候;)

关于javascript - ES 模块命名导入是否可以实现 native Node 绝对(即根相对)路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73140041/

相关文章:

javascript - 更新现有列表而不重新加载整个页面

typescript - 在 Azure Typescript 函数中使用 ES 模块包

javascript - 确定运行更新脚本的理想间隔时间

javascript - window.setTimeout 无法正常运行

javascript - Promise 链接成功和拒绝功能

javascript - 如何通过单击按钮来 document.write( )

javascript - 如何在 Passport/Node js 中找出 last_login_date

node.js - 无法访问 connect-mongo 的原型(prototype)函数

reactjs - 从URL动态加载React组件库?