[Babel7] Does not resolve module for monorepo with babel-node
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
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?
I've made a repo with the error I can reproduce: https://github.com/jibees/babel7-node-test/tree/original-error
-
rootModeoption inbabel-nodehas just been merged 14 days ago : https://github.com/babel/babel/pull/9148 and released inv7.2.2 (2018-12-15)(https://github.com/babel/babel/releases/tag/v7.2.2) Even if I test with--root-mode=upwardthe issue is still hereCannot 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 ;)
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.
Note that this works:
"module-resolver",
{
resolvePath(sourcePath) {
switch (sourcePath) {
case "@package1":
return path.resolve(__dirname, "packages/package-1");
default:
console.log(sourcePath);
}
}
}
@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).
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
Add at the top:
const path = require('path')
It's a core module.
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...
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'],
});
It works ;) Thanks a lot !
Can this issue be closed?
This is still an issue for me. When using monorepo
@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',
},
},
],
],
};
@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.jsFor 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
@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
Did you try to remove babelrcRoots? I believe that by placing the babel.config.js configuration in each package, babelrcRoots becomes unnecessary, correct?