If you've begun to embrace all the new features you get to use with io.js, your app will probably not run on latest node.js (0.12). const
and let
are only available when running node with the --harmony
flag and template strings don't work at all.
I had this problem recently with a little tool I built, gitclick. I was coding away under io.js and only after I released it to the public did I realise that it is not compatible with node.js. At first, I dismissed the issue and proposed everyone to upgrade to io.js. A day later I must say that it was pretty naive of me to think that anybody would upgrade just to use my tool.
I did not want to rewrite my entire app to work with ES5 so I decided to come up with a different solution: running my app through Babel, but only if the user is not on io.js (to retain the best performance there).
A sample application: say-hello
It really is simple to get this setup, but I created a little demo project anyway. Here is how it will work:
- Type
say-hello
- If io.js is running, you will get
Hello io.js
- If node.js is running, you will get
Hello node.js
Check out the GitHub repository for quick access to the "solution".
Step 1: Create your package.json and install dependencies
package.json
JSON
{"name": "say-hello"}
Terminal:
$ npm i is-iojs -S
Step 2: Write the app
bin/say-hello
JS
#!/usr/bin/env node'use strict'const iojs = require('is-iojs')const engine = iojs ? 'io.js' : 'node.js'console.log(`Hello ${engine}`)
Step 3: Create a node.js-compatible wrapper
Above code would not run on the latest version of node.js because it is using features of ES6 that aren't supported there yet. This is why, we will use Babel to compile the code down to ES5 before running it on node.js. So first, install Babel as well:
Terminal:
$ npm i babel -S
Next, create a wrapper-file that runs our app through Babel if we are on a node.js platform.
bin/say-hello-harmony
JS
#!/usr/bin/env node'use strict'var iojs = require('is-iojs')if (!iojs) {require('babel/register')({ ignore: /say-hello\/node_modules/ })}require('./say-hello')
There is an interesting little thing about this line and the ignore
option:
JS
require('babel/register')({ ignore: /say-hello\/node_modules/ })
Babel ignores files within any node_modules
folder by default. If you npm install
a module globally, it usually goes into a directory like /usr/local/lib/node_modules
. Therefore, without the above line, Babel would not register properly because your module itself is inside a node_modules
folder when installed globally.
It took me a few hours to figure out why require('babel/register')
would work if I npm link
a module but not if I'm installing it globally via npm. Now I know and you do too! :)
Step 4: Final steps
Now we're almost done. Just simply make sure that correct bin-file is specified in your package.json
.
package.json
JSON
{"name": "say-hello","bin": "bin/say-hello-harmony","dependencies": {"babel": "^5.1.10","is-iojs": "^1.1.0"}}
Next, enter the following command to make the say-hello
command available in your terminal.
Terminal:
$ npm link
That was it. If you're using a version manager like n (n is awesome!), you can easily test if everything works:
$ node -vv0.12.2$ say-helloHello node.js$ n io latest$ node -vv1.7.1$ say-helloHello io.js