使用es6和babel-node从根目录导入节点模块

44

我正在使用Babel转译器,用ES6编写Node应用程序。

我的根目录中有2个文件index.jsmy-module.js

- index.js
- my-module.js

my-module.js

export let myFunc = () => {
  console.log('myFunc was called!!!');
}

index.js

import {myFunc} from './my-module';
myFunc();

如果我从命令行运行以下代码,一切都会按预期工作。

$ babel-node index.js >> myFunc was called!!!

但是如果我在导入my-module时去掉了点:

import {myFunc} from '/my-module';
myFunc();

我遇到一个错误:

Error: Cannot find module '/my-module'
任何原因导致我无法使用绝对路径导入模块?有没有方法可以更改.babelrc配置文件以支持它?谢谢。
3个回答

56

就像(几乎)所有工具一样,“/x”表示您文件系统根目录中的“x”。 Babel实际上并不查看路径,它只是编译。

import {myFunc} from '/my-module';

进入

var _myModule = require('/my-module');

节点(node)实际上查找了该模块。


如果你真的想相对于项目根目录导入,可以使用插件。我建议使用一些不太含糊的东西,并确保为下一个阅读你代码的人记录这个!

这里有一个例子,我们使用前导符号~表示项目相关。你可以使用任何你喜欢的东西,例如^也是不错的选择。

示例输入:

import {a} from '~my-module';
import {b} from '/my-module';
import {c} from './my-module';

脚本/scripts/babel-plugin-project-relative-require.js

module.exports = function (babel) {
  // get the working directory
  var cwd = process.cwd();

  return new babel.Transformer("babel-plugin-project-relative-require", {
    ImportDeclaration: function(node, parent) {
      // probably always true, but let's be safe
      if (!babel.types.isLiteral(node.source)) {
        return node;
      }

      var ref = node.source.value;

      // ensure a value, make sure it's not home relative e.g. ~/foo
      if (!ref || ref[0] !== '~' || ref[1] === '/') {
        return node;
      }

      node.source.value = cwd + '/' + node.source.value.slice(1);

      return node;
    }
  });
};

.babelrc

{
    "plugins": [
        "./scripts/babel-plugin-project-relative-require.js"
    ]
}

输出(如果在 /tmp 中运行):

'use strict';

var _tmpMyModule = require('/tmp/my-module');

var _myModule = require('/my-module');

var _myModule2 = require('./my-module');

顺便说一下,当我运行你附加的插件时,我得到了以下错误:TypeError: 插件“./scripts/babel-plugin-project-relative-require.js”没有导出Plugin实例 - Gavriguy
1
@Gavriguy 更新 Babel 吗?确保本地和全局版本都是最新的,npm i -g babel@latest; npm i -D babel-core@latest - Brigand
一旦我将插件打包为节点模块(npm install https://github.com/gavriguy/babel-plugin-project-relative-require.git --save),它就像魅力一样工作。非常感谢@FakeRainBrigand。 - Gavriguy

41

FakeRainBrigand/Gavriguy提供的解决方案非常好,而且效果很好。因此,我决定开发一个插件,您可以使用npm轻松安装,并使用一个简单的Babel-Plugin。

https://github.com/michaelzoidl/babel-root-import

希望这有所帮助...


1
这个插件在Windows操作系统中的sourcePath存在一些问题,但在Linux上运行良好。 - Borjante
2
请再检查一下 :) 自从上次发布以来,我们支持Windows操作系统 \o/ - Michael J. Zoidl

7

首先,Babel只是将ES2015语法转换为ES5语法的编译器。它的工作是将以下代码进行转换:

import {myFunc} from '/my-module'

将这段文本转化为:

var _myModule = require('/my-module');

实际需要由Node执行的模块以及Node如何执行它,你可以在此详细阅读:https://nodejs.org/api/modules.html#modules_file_modules
简而言之,./module 表示相对于本地目录的模块路径,/module 是指模块的绝对路径,module 会让Node在本地node_modules目录和所有上级目录中查找该模块。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接