I have developed a javascript CLI app that is using ES2015 code with babel as compiler. (babel-require hook)
The app works perfectly locally, but when I publish on npm, it stops working (babel does not seem to compile the ES2015 files anymore)
Setup:
sample ./bootstrap.js
(ES5):
require('babel-register');
require('./src/app.js');
sample ./src/app.js
(ES2015):
import package from 'package';
...
sample ./bin/myapp
:
#!/usr/bin/env node
require('../bootstrap.js');
Running locally works:
appdir$ ./bin/myapp
I'm running fine!
appdir$
Running globally (after npm install) breaks:
$ sudo npm install -g myapp
└── [email protected]
$ myapp
/usr/local/lib/node_modules/myapp/src/app.js:1
(function (exports, require, module, __filename, __dirname) { import package from 'package';
^^^^^^
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:404:25)
at Module._extensions..js (module.js:432:10)
at Object.require.extensions.(anonymous function) [as .js] (/usr/local/lib/node_modules/myapp/node_modules/babel-register/lib/node.js:138:7)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:313:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.<anonymous> (/usr/local/lib/node_modules/myapp/server.js:9:12)
at Module._compile (module.js:425:26)
Versions:
├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ ├── [email protected]
What I have tried:
ignore: false
in my .babelrc
file hoping it would enable compilation.babelrc
fileNo luck :/
@babel/register uses Node's require() hook system to compile files on the fly when they are loaded. While this is quite helpful overall, it means that there can be confusing cases where code within a require() hook causes more calls to require , causing a dependency cycle.
Not meant for production useYou should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly. Check out the example Node.
And many frameworks today use Babel under the hood to compile their code. For example, Node can't use ES6 import and export statements and some other cool features of ES6 syntax without the help of a compiler like Babel.
Simply add a "scripts" field to your package. json and put the babel command inside there as build . This will run Babel the same way as before and the output will be present in lib directory, only now we are using a local copy. Alternatively, you can reference the babel cli inside of node_modules .
Ok, I figured out what was the issue. I was on the right track thinking there was something forbidding the compilation to happen.
TL;DR
babel-register
hook does not take ignore
and only
options from the .babelrc
file, but it does from its arguments.
The fix in ./bootstrap.js
:
require('babel-register')({
ignore: [],
only: [/src/],
});
require('./src/app.js');
ignore
switch will disable ignoring files which match node_modules
in their path, which is the case for every global module.only
switch then enables compilation of the files of my project src
directory.Now, if you're interested, I will describe the steps I took to resolve the issue, because I think I did it right (this time :))...
Story of the troubleshooting:
First, I needed to install node-debug
commandline tool
$ sudo npm install -g node-inspector
Then launch my app with it (--debug-brk
switch asks to stop execution at first line)
$ node-debug --debug-brk myapp
Open my browser at the local URL provided by node-debug
, and voila see my app code
require('./scr/app.js');
statementObject.require.extension
method, in file babel-register/lib/node.js
, that ignore
and only
variables were undefined
, despite I wanted them to be defined!I stepped inside the method shouldIgnore
of the same file, which confirmed my fears : this function checks for node_modules
in the path, if !ignore && !only
and returns true
(ignore file) if it matches. This is ultimately what caused my ES2015 files to not compile.
babel-register/lib/node.js:120:
function shouldIgnore(filename) {
if (!ignore && !only) { // here `ignore` and `only` were null, despite .babelrc values
return getRelativePath(filename).split(_path2["default"].sep).indexOf("node_modules") >= 0;
} else {
return _babelCore.util.shouldIgnore(filename, ignore || [], only);
}
}
I then guessed that I would have to specify thoses switches directly in babe-register
arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With