繁体   English   中英

ES 模块命名导入是否可以使用本机节点绝对(即根相对)路径?

[英]Are Native Node Absolute (ie. Root-Relative) Paths Possible With ES Module Named Imports?

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

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

你可以这样做:

import { foo } from 'src/bar'

However, that only works if you use the esm package (ie. node -r esm esm ): NODE_PATH doesn't work with native ES Modules (ie. adding "type": "module" to package.json )... so what是现代替代品吗?

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

  • 本地文件(即 `"dependencies": { "src": "file:./src",) - 甚至无法正常工作
  • 符号链接(即从node_modules/src添加符号链接到project-root/src ) - 将文件导入为 CommonJS package,而不是 ES,这意味着命名导入不起作用
  • 工作区(即"workspaces": ["src"],package.json中) - 同样的问题:没有命名导入
  • 导入(即"imports": {"#src": "./src"} ) - 忽略--experimental-specifier-resolution=node标志(所以它只有在我想通过 go 并手动添加.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 年的某个时候;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM