babel-plugin-module-resolver icon indicating copy to clipboard operation
babel-plugin-module-resolver copied to clipboard

[Babel7] Does not resolve module for monorepo with babel-node

Open jibees opened this issue 7 years ago • 16 comments

Hi there,

I have a monorepo designed like this:

- packages
-- package-1
-- package-2
babel.config.js

In packages/package-2 I have a script defined in package.json like this:

"dev": "babel-node --config-file ../../babel.config.js ./index.js",

The babel config for module-resolver is :

 const plugins = [
    [
      "module-resolver",
      {
        cwd: "packagejson",
        root: "./",
        alias: {
          "@package1": "./packages/package-1"
        }
      }
    ]
  ];

The babel config is loaded, but can't resolve the module './packages/package-1' :

Error: Cannot find module './packages/package-1'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> ([...]/packages/package-2/index.js:1:1)
    at Module._compile (module.js:653:30)
    at Module._compile ([...]/node_modules/pirates/lib/index.js:83:24)
    at Module._extensions..js (module.js:664:10)
    at Object.newLoader [as .js] ([...]/node_modules/pirates/lib/index.js:88:7)
    at Module.load (module.js:566:32)

Thanks a lot !

EDIT: workaround for me : using yarn workspaces https://yarnpkg.com/lang/en/docs/workspaces/#toc-how-to-use-it

jibees avatar Dec 11 '18 08:12 jibees

There could be a few issues here.

First, it appears you run the command from the sub-package folder, so babel may see ./ (root) as the folder you are running the command from. Instead of providing a relative path to babel.config.js, have a look at providing babel-node with rootMode: 'upward'.

Then, try "@package1": "packages/package-1", although I'll be surprised if this is the issue.

Finally, could you show the line you use to import the package in index.js?

Izhaki avatar Dec 21 '18 01:12 Izhaki

I've made a repo with the error I can reproduce: https://github.com/jibees/babel7-node-test/tree/original-error

  • rootMode option in babel-node has just been merged 14 days ago : https://github.com/babel/babel/pull/9148 and released in v7.2.2 (2018-12-15) (https://github.com/babel/babel/releases/tag/v7.2.2) Even if I test with --root-mode=upward the issue is still here Cannot find module './packages/package-1'

  • It's the same with "@package1": "packages/package-1" (i've already test this one ;))

  • The line is import Package1 from "@package1";

Thanks a lot ;)

jibees avatar Dec 21 '18 09:12 jibees

Well if you do this:

    [
      "module-resolver",
      {
        root: 'xxxxxxxxxxxxxxxxxxxx',
        alias: {
          "@package1": "../package-1"
        }
      }
    ]

It does pickup package-1, which suggests that the root property is ignored and it uses cwd to resolve the alias path.

Izhaki avatar Dec 21 '18 11:12 Izhaki

Note that this works:

      "module-resolver",
      {
        resolvePath(sourcePath) {
          switch (sourcePath) {
            case "@package1":
              return path.resolve(__dirname, "packages/package-1");
            default:
              console.log(sourcePath);
          }
        }
      }

Izhaki avatar Dec 21 '18 12:12 Izhaki

@tleunen I think there's an issue with the plugin: It doesn't resolve the root correctly when using babel.config.js which is central to mono-repos with babel 7 (docs).

Izhaki avatar Dec 21 '18 13:12 Izhaki

Note that this works:

      "module-resolver",
      {
        resolvePath(sourcePath) {
          switch (sourcePath) {
            case "@package1":
              return path.resolve(__dirname, "packages/package-1");
            default:
              console.log(sourcePath);
          }
        }
      }

I got the error : path is not defined And if I replace by sourcePath, I got sourcePath.resolve is not a function

jibees avatar Dec 21 '18 13:12 jibees

Add at the top:

const path = require('path')

It's a core module.

Izhaki avatar Dec 21 '18 13:12 Izhaki

Ooops, sorry.

Done this, by got a new error:

(function (exports, require, module, __filename, __dirname) { import _foo from "@jibees/package1/src/foo";
                                                              ^^^^^^

SyntaxError: Unexpected token import

Strange...

jibees avatar Dec 21 '18 13:12 jibees

That's because babel does not build anything outside the current cwd. You'd need to override the ignore option to only include node_modules. This is how I do this, albeit with babel/register:

require('@babel/register')({
  // Find babel.config.js up the folder structure.
  rootMode: 'upward',

  // Since babel ignores all files outside the cwd, it does not compile sibling packages
  // So rewrite the ignore list to only include node_modules
  ignore: ['node_modules'],
});

Izhaki avatar Dec 21 '18 14:12 Izhaki

It works ;) Thanks a lot !

jibees avatar Dec 21 '18 14:12 jibees

Can this issue be closed?

Izhaki avatar Sep 11 '19 22:09 Izhaki

This is still an issue for me. When using monorepo

snaerth avatar May 06 '20 13:05 snaerth

@snaerth

I had the same problem as you. I solved it by creating a specific babel.config.js for each package and extending it to the root babel.config.js.

packages
- package-1
-- utils
-- components
-- babel.config.js
- package-2
-- src
-- babel.config.js
babel.config.js

For each babel.config, I have this configuration:

module.exports = {
  extends: './../../babel.config.js',
  plugins: [
    [
      'module-resolver',
      {
        alias: {
          '@utils': './utils',
          '@components': './components',
        },
      },
    ],
  ],
};

avallonazevedo avatar May 11 '20 18:05 avallonazevedo

@snaerth

I had the same problem as you. I solved it by creating a specific babel.config.js for each package and extending it to the root babel.config.js.

packages
- package-1
-- utils
-- components
-- babel.config.js
- package-2
-- src
-- babel.config.js
babel.config.js

For each babel.config, I have this configuration:

module.exports = {
  extends: './../../babel.config.js',
  plugins: [
    [
      'module-resolver',
      {
        alias: {
          '@utils': './utils',
          '@components': './components',
        },
      },
    ],
  ],
};

@avallonazevedo fantastic thank you

snaerth avatar May 11 '20 19:05 snaerth

@avallonazevedo this does not work when you have babelrcRoots configured. This is my base config

module.exports = api => {
  api.cache(true);

  const presets = [
    [
      '@babel/env',
      {
        targets: {
          browsers: ['last 2 versions', 'safari >= 10', 'ie 11'],
        },
        // Exclude transforms that make all code slower
        exclude: ['transform-typeof-symbol'],
      },
    ],
    '@babel/react',
    '@babel/flow',
  ];

  const plugins = [
    '@babel/plugin-transform-modules-commonjs',
    '@babel/plugin-proposal-object-rest-spread',
    '@babel/plugin-transform-regenerator',
    '@babel/plugin-transform-runtime',
    // insert before @babel/plugin-proposal-class-properties
    '@babel/plugin-transform-flow-strip-types',
    [
      '@babel/plugin-proposal-class-properties',
      {
        loose: true,
      },
    ],
  ];

  const env = {
    development: {
      plugins: ['react-hot-loader/babel'],
    },
    production: {
      plugins: [
        '@babel/plugin-transform-react-constant-elements',
        '@babel/plugin-transform-react-inline-elements',
      ],
    },
  };

  const babelrcRoots = [
    // Keep the root as a root
    '.',
    // Also consider monorepo packages "root" and load their .babelrc.json.
    './packages/*',
  ];

  return {
    presets,
    plugins,
    env,
    babelrcRoots,
    ignore: ['node_modules'],
  };
};

and this is the package config

module.exports = api => {
  api.cache(true);

  const plugins = [
    [
      'module-resolver',
      {
        alias: {
          '@static': './static',
        },
      },
    ],
  ];

  return {
    extends: "../../babel.config.js",
    plugins,
  };
};

And the error is classic Error: .babelrcRoots is not allowed in .babelrc or "extends"ed files, only in root programmatic options, or babel.config.js/config file options

snaerth avatar May 12 '20 11:05 snaerth

@snaerth

Did you try to remove babelrcRoots? I believe that by placing the babel.config.js configuration in each package, babelrcRoots becomes unnecessary, correct?

avallonazevedo avatar May 12 '20 14:05 avallonazevedo