Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Likely bug in babel-node within monorepos, does not seem to accept --config-file or --root-mode options in its cli #10954

Open
JZBo opened this issue Jan 3, 2020 · 3 comments
Labels

Comments

@JZBo
Copy link

@JZBo JZBo commented Jan 3, 2020

Bug Report

Hello and thanks for your constant work on babel,
I would like to report what I think is definitely a bug, or at least an unintended behaviour difference between babel and babel-node, both in version 7.7.7.

A short summary:
In a monorepo, the babel cli can correctly use either the "--root-mode upward" and the "--config-file" to refer to the root config file "babel.config.js" when launched outside the root directory of the monorepo.
HOWEVER, babel-node does not seem to react to either option when launched in a subpackage, while still recognizing those options if launched from the root directory.

Current Behavior
Let me try to explain myself better:
I have a the equivalent of a monorepo (a two package.json electron project), with some babel scripts launching from outside the root directory (the subpackage).
I made the switch from babel 6x to babel 7x, and I noticed those scripts failing. I thoroughly read all the available documentation about the differences in config-files loading, and how to use babel 7 in monorepos, and applied what I read. However, I still had one script failing, which uses babel-node for a postinstall step and which is launching from the subdirectory:

In the root directory I have a babel.config.js which works as intended, and I have a secondary package.json in an './app' subdirectory.

If in the app subdirectory I launch babel via cli with either
babel --root-mode upward ../scripts/myTarget.js
or with
babel --config-file ../babel.config.js ../scripts/myTarget.js
it works as intended, and would correctly transpile myTarget.js

So far so good.
However, if I try to do the same with babel-node (still within the app subdirectory), either by using
babel-node --root-mode upward ../scripts/myTarget.js
or with
babel-node --config-file ../babel.config.js ../scripts/myTarget.js
Then i get a "SyntaxError: Unexpected identifier" and babel-node does not load the config file, (I can verify if it's loaded or not because I've put a simple console.log at the start of the babel.config.js in the root directory).

This seems to be a bug, especially because if I launch babel-node from the root directory
babel-node --config-file ./app/totallyNotABabelConfig.js ../scripts/myTarget.js
it works, recognizes the config-file option and loads the aptly named alternative config file (again, I can differentiate by a different console.log I have put there).

Expected behavior/code
I would expect babel-node to be able to correctly act according to either the "--root-mode upward" option or to read and apply the "--config-file [path]" as directed, regardless of whether it is launched from the root directory or from a subdirectory of a monorepo.

Babel Configuration (babel.config.js, .babelrc, package.json#babel, cli command, .eslintrc)

  • Dev Dependencies in both the package.json file
{
    "@babel/cli": "^7.7.7",
    "@babel/core": "^7.7.7",
    "@babel/node": "^7.7.7",
}
  • Cli commands results (in the ROOT directory), all working as expected:
$ babel-node ./internals/scripts/myBabelTarget.js                                                          
Loaded ROOT babel.config.js                                                                                
DEBUG test baseName:  myBabelTarget.js                                                                     
                                                                                                           
$ babel ./internals/scripts/myBabelTarget.js                                                               
Loaded ROOT babel.config.js                                                                                
"use strict";                                                                                              
var _path = _interopRequireDefault(require("path"));                                                                                                                                                            
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }            
const testPath = _path.default.basename(__filename);                                                       
console.log('DEBUG test baseName: ', testPath);                                                            
                                                                                                           
$ babel --config-file ./app/totallyNotABabelConfig.js ./internals/scripts/myBabelTarget.js                 
Loaded APP babel.config.js                                                                                 
"use strict";                                                                                              
var _path = _interopRequireDefault(require("path"));                                                       
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }            
const testPath = _path.default.basename(__filename);                                                       
console.log('DEBUG test baseName: ', testPath);                                                            
                                                                                                           
$ babel-node --config-file ./app/totallyNotABabelConfig.js ./internals/scripts/myBabelTarget.js            
Loaded APP babel.config.js                                                                                 
DEBUG test baseName:  myBabelTarget.js
  • Cli commands results (in the ROOT/APP subdirectory), babel working as expected, babel-node not working as expected. (As expected, neither works if no root-mode or config-file are specified):
$ babel ../internals/scripts/myBabelTarget.js                                                                                      
import path from 'path';                                                                                                           
const testPath = path.basename(__filename);                                                                                        
console.log('DEBUG test baseName: ', testPath);                                                                                    
                                                                                                                                                            
$ babel-node ../internals/scripts/myBabelTarget.js                                                                                 
[cut]\internals\scripts\myBabelTarget.js:1                                               
import path from 'path';                                                                                                           
       ^^^^                                                                                                                                                                                                                                                    
SyntaxError: Unexpected identifier                                                                                                 
    at Module._compile (internal/modules/cjs/loader.js:723:23)                                                                     
[...]    

$ babel --config-file ../babel.config.js ../internals/scripts/myBabelTarget.js                                                     
Loaded ROOT babel.config.js                                                                                                        
"use strict";                                                                                                                      
var _path = _interopRequireDefault(require("path"));                                                                               
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }                                    
const testPath = _path.default.basename(__filename);                                                                               
console.log('DEBUG test baseName: ', testPath);                                                                                    
                                                                                                                                   
$ babel-node --config-file ../babel.config.js ../internals/scripts/myBabelTarget.js                                                
[cut]\internals\scripts\myBabelTarget.js:1                                               
import path from 'path';                                                                                                           
       ^^^^                                                                                                                        
SyntaxError: Unexpected identifier                                                                                                 
    at Module._compile (internal/modules/cjs/loader.js:723:23)                                                                     
[...]

$ babel --root-mode upward ../internals/scripts/myBabelTarget.js                                                                   
Loaded ROOT babel.config.js                                                                                                        
"use strict";                                                                                                                      
var _path = _interopRequireDefault(require("path"));                                                                               
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }                                    
const testPath = _path.default.basename(__filename);                                                                               
console.log('DEBUG test baseName: ', testPath);     
                                        
$ babel-node --root-mode upward ../internals/scripts/myBabelTarget.js                                                              
[cut]\internals\scripts\myBabelTarget.js:1                                               
import path from 'path';                                                                                                           
       ^^^^                                                                                                                                                                                                                                                    
SyntaxError: Unexpected identifier                                                                                                 
    at Module._compile (internal/modules/cjs/loader.js:723:23)                                                                     
[...]                                                                               
                                                                                                                                   
$ babel --config-file ./totallyNotABabelConfig.js ../internals/scripts/myBabelTarget.js                                            
Loaded APP babel.config.js                                                                                                         
"use strict";                                                                                                                      
var _path = _interopRequireDefault(require("path"));                                                                               
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }                                    
const testPath = _path.default.basename(__filename);                                                                                                                                                                                                                  
console.log('DEBUG test baseName: ', testPath);                                                                                    
     
$ babel-node --config-file ./totallyNotABabelConfig.js ../internals/scripts/myBabelTarget.js                                       
[cut]\internals\scripts\myBabelTarget.js:1                                               
import path from 'path';                                                                                                           
       ^^^^                                                                                                                                                                                                                                                           
SyntaxError: Unexpected identifier                                                                                                 
    at Module._compile (internal/modules/cjs/loader.js:723:23)                                                                     
[...]

Environment

  • Babel version(s): [7.7.7]
  • Node/npm version: [Node 10.16.3, yarn 1.9.1]
  • OS: [Windows 7 Pro]
  • Monorepo: [yes]
  • How you are using Babel: [cli]

Possible Solution
Unfortunately I have no suggestions.

@babel-bot

This comment has been minimized.

Copy link
Collaborator

@babel-bot babel-bot commented Jan 3, 2020

Hey @JZBo! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite."

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jan 8, 2020

Next time please post a clear example of your directory structure 🙏
I managed to reproduce the bug with this one:

.
├── app
│   ├── package.json
│   └── totallyNotABabelConfig.json
├── internals
│   ├── package.json
│   └── scripts
│       └── myBabelTarget.js
├── babel.config.js
├── package.json
└── yarn.lock

As a side note (but it's not the cause of the bug) you are not using the babel and babel-node installed in your package.json but the globally installed packages. You should either run ./node_modules/.bin/babel ..., npx babel ... or yarn babel ....

@nicolo-ribaudo

This comment has been minimized.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jan 8, 2020

The problem is that, by design, @babel/register and @babel/node only compile the current cwd:

if (transformOpts.ignore === undefined && transformOpts.only === undefined) {
transformOpts.only = [
// Only compile things inside the current working directory.
new RegExp("^" + escapeRegExp(cwd), "i"),
];
transformOpts.ignore = [
// Ignore any node_modules inside the current working directory.
new RegExp(
"^" +
escapeRegExp(cwd) +
"(?:" +
path.sep +
".*)?" +
escapeRegExp(path.sep + "node_modules" + path.sep),
"i",
),
];
}

As a workaround you can pass a custom --ignore:

../node_modules/.bin/babel-node --config-file ../babel.config.js ../internals/scripts/myBabelTarget.js --ignore node_modules

or

../node_modules/.bin/babel-node --config-file ../babel.config.js ../internals/scripts/myBabelTarget.js --ignore ""

This is done for safety reasons, but I think that the intended behavior should to ignore everything outside of the root (i.e. where the config file is found) rather than using cwd. I'm not sure if this can be fixed without breaking anything, or should be done in Babel 8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.