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
└── myapp@0.1.0
$ 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:
├─┬ babel-register@6.4.3
│ │ ├─┬ babel-core@6.4.5
│ │ │ ├─┬ babel-code-frame@6.3.13
│ │ │ ├─┬ babel-generator@6.4.5
│ │ │ ├── babel-helpers@6.4.5
│ │ ├── babel-runtime@5.8.35
What I have tried:
- Adding
ignore: false
in my .babelrc
file hoping it would enable compilation
- using options in require hook arguments instead of
.babelrc
file
No luck :/
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: false,
only: /myapp\/src/
});
require('./src/app.js');
- The
ignore
switch will disable ignoring files which match node_modules
in their path, which is the case for every global module.
- The
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
- Place a breakpoint the line just above the
require('./scr/app.js');
statement
- Click 'play' to continue process execution until that line
- Here starts the tedious task of climbing the error trace using 'step over' and 'step inside' buttons : when the next statement is 'outside' of your error trace (see the one above in the question), I could 'step over'. If the next statement is one of the functions of the trace, 'step in'.
- I then realized, by looking at the 'scope variable' watches, when in the
Object.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.